* [PATCH v4 net-next 1/9] net: enetc: add interfaces to manage dynamic FDB entries
From: wei.fang @ 2026-06-09 3:29 UTC (permalink / raw)
To: claudiu.manoil, vladimir.oltean, xiaoning.wang, andrew+netdev,
davem, edumazet, kuba, pabeni, chleroy, andrew, olteanv, linux
Cc: wei.fang, imx, netdev, linux-kernel, linuxppc-dev,
linux-arm-kernel
In-Reply-To: <20260609032955.2066089-1-wei.fang@oss.nxp.com>
From: Wei Fang <wei.fang@nxp.com>
Add three interfaces to manage dynamic entries in the FDB table:
ntmp_fdbt_update_activity_element(): Update the activity element of all
dynamic FDB entries. For each entry, if its activity flag is not set,
which means no packet has matched this entry since the last update, the
activity counter is incremented. Otherwise, both the activity flag and
activity counter are reset. The activity counter is used to track how
long an FDB entry has been inactive, which is useful for implementing
an ageing mechanism.
ntmp_fdbt_delete_ageing_entries(): Delete all dynamic FDB entries whose
activity flag is not set and whose activity counter is greater than or
equal to the specified threshold. This is used to remove stale entries
that have been inactive for too long.
ntmp_fdbt_delete_port_dynamic_entries(): Delete all dynamic FDB entries
associated with the specified switch port. This is typically called when
a port goes down or is removed from a bridge.
Signed-off-by: Wei Fang <wei.fang@nxp.com>
---
drivers/net/ethernet/freescale/enetc/ntmp.c | 162 ++++++++++++++++++
.../ethernet/freescale/enetc/ntmp_private.h | 4 +-
include/linux/fsl/ntmp.h | 3 +
3 files changed, 167 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/freescale/enetc/ntmp.c b/drivers/net/ethernet/freescale/enetc/ntmp.c
index f71cad943424..bda26fe93b8d 100644
--- a/drivers/net/ethernet/freescale/enetc/ntmp.c
+++ b/drivers/net/ethernet/freescale/enetc/ntmp.c
@@ -31,6 +31,7 @@
#define NTMP_GEN_UA_STSEU BIT(1)
/* Specific Update Actions for some tables */
+#define FDBT_UA_ACTEU BIT(1)
#define BPT_UA_BPSEU BIT(1)
/* Query Action: 0: Full query. 1: Query entry ID, the fields after entry
@@ -793,6 +794,167 @@ int ntmp_fdbt_search_port_entry(struct ntmp_user *user, int port,
}
EXPORT_SYMBOL_GPL(ntmp_fdbt_search_port_entry);
+/**
+ * ntmp_fdbt_update_activity_element - update the activity element of all
+ * the dynamic entries in the FDB table.
+ * @user: target ntmp_user struct
+ *
+ * A single activity update management could be used to process all the
+ * dynamic entries in the FDB table. When hardware process an activity
+ * update management command for an entry in the FDB table and the entry
+ * does not have its activity flag set, the activity counter is incremented.
+ * However, if the activity flag is set, then both the activity flag and
+ * activity counter are reset. Software can issue the activity update
+ * management commands at predefined times and the value of the activity
+ * counter can then be used to estimate the period of how long an FDB
+ * entry has been inactive.
+ *
+ * Return: 0 on success, otherwise a negative error code
+ */
+int ntmp_fdbt_update_activity_element(struct ntmp_user *user)
+{
+ struct fdbt_req_ua *req;
+ struct netc_swcbd swcbd;
+ struct netc_cbdr *cbdr;
+ union netc_cbd cbd;
+ u32 len;
+ int err;
+
+ swcbd.size = sizeof(*req);
+ err = ntmp_alloc_data_mem(user->dev, &swcbd, (void **)&req);
+ if (err)
+ return err;
+
+ /* Request data */
+ ntmp_fill_crd(&req->crd, user->tbl.fdbt_ver, 0, FDBT_UA_ACTEU);
+ req->ak.search.resume_eid = cpu_to_le32(NTMP_NULL_ENTRY_ID);
+ req->ak.search.cfge.cfg = cpu_to_le32(FDBT_DYNAMIC);
+ req->ak.search.cfge_mc = FDBT_CFGE_MC_DYNAMIC;
+
+ /* Request header */
+ len = NTMP_LEN(swcbd.size, NTMP_STATUS_RESP_LEN);
+ /* For activity update, the access method must be search */
+ ntmp_fill_request_hdr(&cbd, swcbd.dma, len, NTMP_FDBT_ID,
+ NTMP_CMD_UPDATE, NTMP_AM_SEARCH);
+
+ ntmp_select_and_lock_cbdr(user, &cbdr);
+ err = netc_xmit_ntmp_cmd(cbdr, &cbd, &swcbd);
+ if (err)
+ dev_err(user->dev,
+ "Failed to update activity of %s, err: %pe\n",
+ ntmp_table_name(NTMP_FDBT_ID), ERR_PTR(err));
+
+ ntmp_unlock_cbdr(cbdr);
+
+ return err;
+}
+EXPORT_SYMBOL_GPL(ntmp_fdbt_update_activity_element);
+
+/**
+ * ntmp_fdbt_delete_ageing_entries - delete all the ageing dynamic entries
+ * in the FDB table
+ * @user: target ntmp_user struct
+ * @act_cnt: the target value of the activity counter
+ *
+ * The matching rule is that the activity flag is not set and the activity
+ * counter is greater than or equal to act_cnt
+ *
+ * Return: 0 on success, otherwise a negative error code
+ */
+int ntmp_fdbt_delete_ageing_entries(struct ntmp_user *user, u8 act_cnt)
+{
+ struct fdbt_req_qd *req;
+ struct netc_swcbd swcbd;
+ struct netc_cbdr *cbdr;
+ union netc_cbd cbd;
+ u32 len;
+ int err;
+
+ if (act_cnt > FDBT_ACT_CNT)
+ return -EINVAL;
+
+ swcbd.size = sizeof(*req);
+ err = ntmp_alloc_data_mem(user->dev, &swcbd, (void **)&req);
+ if (err)
+ return err;
+
+ /* Request data */
+ ntmp_fill_crd(&req->crd, user->tbl.fdbt_ver, 0, 0);
+ req->ak.search.resume_eid = cpu_to_le32(NTMP_NULL_ENTRY_ID);
+ req->ak.search.cfge.cfg = cpu_to_le32(FDBT_DYNAMIC);
+ req->ak.search.acte = act_cnt;
+ /* Exact match with ACTE_DATA[ACT_FLAG] AND
+ * match >= ACTE_DATA[ACT_CNT]
+ */
+ req->ak.search.acte_mc = FDBT_ACTE_MC;
+ req->ak.search.cfge_mc = FDBT_CFGE_MC_DYNAMIC;
+
+ /* Request header */
+ len = NTMP_LEN(swcbd.size, NTMP_STATUS_RESP_LEN);
+ ntmp_fill_request_hdr(&cbd, swcbd.dma, len, NTMP_FDBT_ID,
+ NTMP_CMD_DELETE, NTMP_AM_SEARCH);
+
+ ntmp_select_and_lock_cbdr(user, &cbdr);
+ err = netc_xmit_ntmp_cmd(cbdr, &cbd, &swcbd);
+ if (err)
+ dev_err(user->dev,
+ "Failed to delete ageing entries of %s, err: %pe\n",
+ ntmp_table_name(NTMP_FDBT_ID), ERR_PTR(err));
+
+ ntmp_unlock_cbdr(cbdr);
+
+ return err;
+}
+EXPORT_SYMBOL_GPL(ntmp_fdbt_delete_ageing_entries);
+
+/**
+ * ntmp_fdbt_delete_port_dynamic_entries - delete all dynamic FDB entries
+ * associated with the specified switch port
+ * @user: target ntmp_user struct
+ * @port: the specified switch port ID
+ *
+ * Return: 0 on success, otherwise a negative error code
+ */
+int ntmp_fdbt_delete_port_dynamic_entries(struct ntmp_user *user, int port)
+{
+ struct fdbt_req_qd *req;
+ struct netc_swcbd swcbd;
+ struct netc_cbdr *cbdr;
+ union netc_cbd cbd;
+ u32 len;
+ int err;
+
+ swcbd.size = sizeof(*req);
+ err = ntmp_alloc_data_mem(user->dev, &swcbd, (void **)&req);
+ if (err)
+ return err;
+
+ /* Request data */
+ ntmp_fill_crd(&req->crd, user->tbl.fdbt_ver, 0, 0);
+ req->ak.search.resume_eid = cpu_to_le32(NTMP_NULL_ENTRY_ID);
+ req->ak.search.cfge.port_bitmap = cpu_to_le32(BIT(port));
+ req->ak.search.cfge.cfg = cpu_to_le32(FDBT_DYNAMIC);
+ /* Match CFGE_DATA[DYNAMIC & PORT_BITMAP] field */
+ req->ak.search.cfge_mc = FDBT_CFGE_MC_DYNAMIC_AND_PORT_BITMAP;
+
+ /* Request header */
+ len = NTMP_LEN(swcbd.size, NTMP_STATUS_RESP_LEN);
+ ntmp_fill_request_hdr(&cbd, swcbd.dma, len, NTMP_FDBT_ID,
+ NTMP_CMD_DELETE, NTMP_AM_SEARCH);
+
+ ntmp_select_and_lock_cbdr(user, &cbdr);
+ err = netc_xmit_ntmp_cmd(cbdr, &cbd, &swcbd);
+ if (err)
+ dev_err(user->dev,
+ "Failed to delete dynamic %s entries on port %d, err: %pe\n",
+ ntmp_table_name(NTMP_FDBT_ID), port, ERR_PTR(err));
+
+ ntmp_unlock_cbdr(cbdr);
+
+ return err;
+}
+EXPORT_SYMBOL_GPL(ntmp_fdbt_delete_port_dynamic_entries);
+
/**
* ntmp_vft_add_entry - add an entry into the VLAN filter table
* @user: target ntmp_user struct
diff --git a/drivers/net/ethernet/freescale/enetc/ntmp_private.h b/drivers/net/ethernet/freescale/enetc/ntmp_private.h
index 0a9b87286105..ad532b059ba8 100644
--- a/drivers/net/ethernet/freescale/enetc/ntmp_private.h
+++ b/drivers/net/ethernet/freescale/enetc/ntmp_private.h
@@ -155,8 +155,8 @@ struct fdbt_ak_search {
#define FDBT_KEYE_MAC GENMASK(1, 0)
u8 cfge_mc;
#define FDBT_CFGE_MC GENMASK(2, 0)
-#define FDBT_CFGE_MC_ANY 0
-#define FDBT_CFGE_MC_DYNAMIC 1
+#define FDBT_CFGE_MC_ANY 0
+#define FDBT_CFGE_MC_DYNAMIC 1
#define FDBT_CFGE_MC_PORT_BITMAP 2
#define FDBT_CFGE_MC_DYNAMIC_AND_PORT_BITMAP 3
u8 acte_mc;
diff --git a/include/linux/fsl/ntmp.h b/include/linux/fsl/ntmp.h
index 88166f9ad3a2..5db078e1caa0 100644
--- a/include/linux/fsl/ntmp.h
+++ b/include/linux/fsl/ntmp.h
@@ -263,6 +263,9 @@ int ntmp_fdbt_delete_entry(struct ntmp_user *user, u32 entry_id);
int ntmp_fdbt_search_port_entry(struct ntmp_user *user, int port,
u32 *resume_entry_id,
struct fdbt_entry_data *entry);
+int ntmp_fdbt_update_activity_element(struct ntmp_user *user);
+int ntmp_fdbt_delete_ageing_entries(struct ntmp_user *user, u8 act_cnt);
+int ntmp_fdbt_delete_port_dynamic_entries(struct ntmp_user *user, int port);
int ntmp_vft_add_entry(struct ntmp_user *user, u16 vid,
const struct vft_cfge_data *cfge);
int ntmp_bpt_update_entry(struct ntmp_user *user, u32 entry_id,
--
2.34.1
^ permalink raw reply related
* [PATCH v4 net-next 0/9] net: dsa: netc: add bridge mode support
From: wei.fang @ 2026-06-09 3:29 UTC (permalink / raw)
To: claudiu.manoil, vladimir.oltean, xiaoning.wang, andrew+netdev,
davem, edumazet, kuba, pabeni, chleroy, andrew, olteanv, linux
Cc: wei.fang, imx, netdev, linux-kernel, linuxppc-dev,
linux-arm-kernel
From: Wei Fang <wei.fang@nxp.com>
This series adds bridge mode support to the NETC DSA switch driver,
covering both VLAN-aware and VLAN-unaware operation.
The NETC switch manages forwarding through a set of hardware tables
accessed via NTMP: the FDB table (FDBT), VLAN filter table (VFT), egress
treatment table (ETT), and egress count table (ECT). The series extends
the NTMP layer with the operations required for bridging, then builds the
DSA bridge callbacks on top.
Since all switch ports share the VFT, so only one VLAN-aware bridge is
supported.
FDB aging is managed in software. A periodic delayed work sweeps the
table using the hardware activity element mechanism, with a default aging
time of 300 seconds matching the IEEE 802.1Q standard. Per-port entries
are also flushed immediately on bridge leave and link-down events.
---
v4:
1. Set ect_eid before calling netc_update_ett_entry() in
netc_port_update_vlan_egress_rule()
2. Improve netc_vlan_unaware_pvid(), use "struct dsa_bridge *bridge" as
its parameter
3. Add comments in netc_port_vlan_filtering() and
netc_port_bridge_leave()
4. Add vid check in netc_port_vlan_del()
v3 link: https://lore.kernel.org/imx/20260605014808.686024-1-wei.fang@oss.nxp.com/
v2 link: https://lore.kernel.org/imx/20260602072313.3162120-1-wei.fang@oss.nxp.com/
v1 link: https://lore.kernel.org/imx/20260527100217.794987-1-wei.fang@oss.nxp.com/
---
Wei Fang (9):
net: enetc: add interfaces to manage dynamic FDB entries
net: enetc: add "Update" and "Delete" operations to VLAN filter table
net: enetc: add interfaces to manage egress treatment table
net: enetc: add "Update" operation to the egress count table
net: dsa: netc: initialize the group bitmap of ETT and ECT
net: enetc: add helpers to set/clear table bitmap
net: dsa: netc: add VLAN filter table and egress treatment management
net: dsa: netc: add bridge mode support
net: dsa: netc: implement dynamic FDB entry ageing
drivers/net/dsa/netc/netc_main.c | 965 +++++++++++++++++-
drivers/net/dsa/netc/netc_switch.h | 33 +
drivers/net/dsa/netc/netc_switch_hw.h | 6 +
drivers/net/ethernet/freescale/enetc/ntmp.c | 440 +++++++-
.../ethernet/freescale/enetc/ntmp_private.h | 18 +-
include/linux/fsl/ntmp.h | 55 +
6 files changed, 1495 insertions(+), 22 deletions(-)
--
2.34.1
^ permalink raw reply
* [PATCH] ARM: PXA: remove remnants of PXA93x support
From: Ethan Nelson-Moore @ 2026-06-09 2:54 UTC (permalink / raw)
To: linux-arm-kernel, linux-mmc
Cc: Ethan Nelson-Moore, Ulf Hansson, Uwe Kleine-König,
Rakuram Eswaran, Binbin Zhou, Khalid Aziz
Support for PXA93x chips was removed in commit d711b8a2987a ("ARM: pxa:
remove pxa93x support"), but some code to handle them remains. Remove
it.
Discovered while searching for CONFIG_* symbols referenced in code but
not defined in any Kconfig file.
Signed-off-by: Ethan Nelson-Moore <enelsonmoore@gmail.com>
---
drivers/mmc/host/pxamci.c | 3 +-
include/linux/soc/pxa/cpu.h | 56 -------------------------------------
2 files changed, 1 insertion(+), 58 deletions(-)
diff --git a/drivers/mmc/host/pxamci.c b/drivers/mmc/host/pxamci.c
index b5ea058ed467..f8427f071c00 100644
--- a/drivers/mmc/host/pxamci.c
+++ b/drivers/mmc/host/pxamci.c
@@ -43,8 +43,7 @@
#define NR_SG 1
#define CLKRT_OFF (~0)
-#define mmc_has_26MHz() (cpu_is_pxa300() || cpu_is_pxa310() \
- || cpu_is_pxa935())
+#define mmc_has_26MHz() (cpu_is_pxa300() || cpu_is_pxa310())
struct pxamci_host {
struct mmc_host *mmc;
diff --git a/include/linux/soc/pxa/cpu.h b/include/linux/soc/pxa/cpu.h
index 5782450ee45c..38bacdae684f 100644
--- a/include/linux/soc/pxa/cpu.h
+++ b/include/linux/soc/pxa/cpu.h
@@ -46,14 +46,6 @@
* PXA31x A2 0x69056892 0x2E649013
* PXA32x B1 0x69056825 0x5E642013
* PXA32x B2 0x69056826 0x6E642013
- *
- * PXA930 B0 0x69056835 0x5E643013
- * PXA930 B1 0x69056837 0x7E643013
- * PXA930 B2 0x69056838 0x8E643013
- *
- * PXA935 A0 0x56056931 0x1E653013
- * PXA935 B0 0x56056936 0x6E653013
- * PXA935 B1 0x56056938 0x8E653013
*/
#ifdef CONFIG_PXA25x
#define __cpu_is_pxa210(id) \
@@ -126,26 +118,6 @@
#define __cpu_is_pxa320(id) (0)
#endif
-#ifdef CONFIG_CPU_PXA930
-#define __cpu_is_pxa930(id) \
- ({ \
- unsigned int _id = (id) >> 4 & 0xfff; \
- _id == 0x683; \
- })
-#else
-#define __cpu_is_pxa930(id) (0)
-#endif
-
-#ifdef CONFIG_CPU_PXA935
-#define __cpu_is_pxa935(id) \
- ({ \
- unsigned int _id = (id) >> 4 & 0xfff; \
- _id == 0x693; \
- })
-#else
-#define __cpu_is_pxa935(id) (0)
-#endif
-
#define cpu_is_pxa210() \
({ \
__cpu_is_pxa210(read_cpuid_id()); \
@@ -186,18 +158,6 @@
__cpu_is_pxa320(read_cpuid_id()); \
})
-#define cpu_is_pxa930() \
- ({ \
- __cpu_is_pxa930(read_cpuid_id()); \
- })
-
-#define cpu_is_pxa935() \
- ({ \
- __cpu_is_pxa935(read_cpuid_id()); \
- })
-
-
-
/*
* CPUID Core Generation Bit
* <= 0x2 for pxa21x/pxa25x/pxa26x/pxa27x
@@ -218,22 +178,11 @@
__cpu_is_pxa300(id) \
|| __cpu_is_pxa310(id) \
|| __cpu_is_pxa320(id) \
- || __cpu_is_pxa93x(id); \
})
#else
#define __cpu_is_pxa3xx(id) (0)
#endif
-#if defined(CONFIG_CPU_PXA930) || defined(CONFIG_CPU_PXA935)
-#define __cpu_is_pxa93x(id) \
- ({ \
- __cpu_is_pxa930(id) \
- || __cpu_is_pxa935(id); \
- })
-#else
-#define __cpu_is_pxa93x(id) (0)
-#endif
-
#define cpu_is_pxa2xx() \
({ \
__cpu_is_pxa2xx(read_cpuid_id()); \
@@ -244,9 +193,4 @@
__cpu_is_pxa3xx(read_cpuid_id()); \
})
-#define cpu_is_pxa93x() \
- ({ \
- __cpu_is_pxa93x(read_cpuid_id()); \
- })
-
#endif
--
2.43.0
^ permalink raw reply related
* [soc:cix/dt] BUILD SUCCESS 4bf90cff838c8ede56216d59f1d64ef25315cfa9
From: kernel test robot @ 2026-06-09 2:50 UTC (permalink / raw)
To: Linus Walleij; +Cc: linux-arm-kernel, arm
tree/branch: https://git.kernel.org/pub/scm/linux/kernel/git/soc/soc.git cix/dt
branch HEAD: 4bf90cff838c8ede56216d59f1d64ef25315cfa9 Merge tag 'cix-dt-v7.2-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/peter.chen/cix into cix/dt
elapsed time: 8958m
configs tested: 5
configs skipped: 231
The following configs have been built successfully.
More configs may be tested in the coming days.
tested configs:
arc allyesconfig gcc-16.1.0
arm64 allmodconfig clang-23
arm64 allnoconfig gcc-16.1.0
loongarch allmodconfig clang-19
riscv allmodconfig clang-23
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply
* [PATCH v9 4/4] arm64: configs: Update defconfig for AST2700 platform support
From: Ryan Chen @ 2026-06-09 2:47 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Joel Stanley,
Andrew Jeffery, Catalin Marinas, Will Deacon, Arnd Bergmann,
Krzysztof Kozlowski, Alexandre Belloni, Linus Walleij,
Drew Fustini, Paul Walmsley, Palmer Dabbelt, Albert Ou,
Alexandre Ghiti
Cc: devicetree, linux-arm-kernel, linux-aspeed, linux-kernel, soc,
linux-riscv, Ryan Chen, Krzysztof Kozlowski
In-Reply-To: <20260609-upstream_ast2700-v9-0-f631752f0cb1@aspeedtech.com>
Enable options for ASPEED AST2700 SoC.
Signed-off-by: Ryan Chen <ryan_chen@aspeedtech.com>
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
---
arch/arm64/configs/defconfig | 1 +
1 file changed, 1 insertion(+)
diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index 909f3c188e75..4879939353f4 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -39,6 +39,7 @@ CONFIG_ARCH_SUNXI=y
CONFIG_ARCH_ALPINE=y
CONFIG_ARCH_APPLE=y
CONFIG_ARCH_ARTPEC=y
+CONFIG_ARCH_ASPEED=y
CONFIG_ARCH_AXIADO=y
CONFIG_ARCH_BCM=y
CONFIG_ARCH_BCM2835=y
--
2.34.1
^ permalink raw reply related
* [PATCH v9 3/4] arm64: dts: aspeed: Add initial AST27xx SoC device tree
From: Ryan Chen @ 2026-06-09 2:47 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Joel Stanley,
Andrew Jeffery, Catalin Marinas, Will Deacon, Arnd Bergmann,
Krzysztof Kozlowski, Alexandre Belloni, Linus Walleij,
Drew Fustini, Paul Walmsley, Palmer Dabbelt, Albert Ou,
Alexandre Ghiti
Cc: devicetree, linux-arm-kernel, linux-aspeed, linux-kernel, soc,
linux-riscv, Ryan Chen
In-Reply-To: <20260609-upstream_ast2700-v9-0-f631752f0cb1@aspeedtech.com>
Add initial device tree support for the ASPEED AST27xx family, the
8th-generation Baseboard Management Controller (BMC) SoCs.
AST27xx SOC Family
- https://www.aspeedtech.com/server_ast2700/
- https://www.aspeedtech.com/server_ast2720/
- https://www.aspeedtech.com/server_ast2750/
The AST27xx features a dual-SoC architecture consisting of two dies,
referred to as SoC0 and SoC1 - interconnected through an internal
proprietary bus. Both SoCs share the same address decoding scheme,
while each maintains independent clock and reset domains.
- SoC0 (CPU die): contains a quad-core Cortex-A35 cluster and two
Cortex-M4 cores, along with high-speed peripherals.
- SoC1 (I/O die): includes the BootMCU (responsible for system
boot) and its own clock/reset domains low-speed peripherals.
The device tree describes the SoC0 and SoC1 domains and their peripheral
layouts.
Signed-off-by: Ryan Chen <ryan_chen@aspeedtech.com>
---
MAINTAINERS | 1 +
arch/arm64/boot/dts/Makefile | 1 +
arch/arm64/boot/dts/aspeed/Makefile | 4 +
.../dts/aspeed/aspeed-evb-flash-layout-128.dtsi | 32 +
arch/arm64/boot/dts/aspeed/aspeed-g7-a35.dtsi | 196 ++++
.../boot/dts/aspeed/aspeed-g7-soc0-pinctrl.dtsi | 225 ++++
arch/arm64/boot/dts/aspeed/aspeed-g7-soc0.dtsi | 230 ++++
.../boot/dts/aspeed/aspeed-g7-soc1-pinctrl.dtsi | 1113 ++++++++++++++++++++
arch/arm64/boot/dts/aspeed/aspeed-g7-soc1.dtsi | 557 ++++++++++
arch/arm64/boot/dts/aspeed/ast2700-evb.dts | 65 ++
10 files changed, 2424 insertions(+)
diff --git a/MAINTAINERS b/MAINTAINERS
index 20bd55913b2d..51d12804ad5a 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2683,6 +2683,7 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/bmc/linux.git
F: Documentation/devicetree/bindings/arm/aspeed/
F: arch/arm/boot/dts/aspeed/
F: arch/arm/mach-aspeed/
+F: arch/arm64/boot/dts/aspeed/
N: aspeed
ARM/AXIADO ARCHITECTURE
diff --git a/arch/arm64/boot/dts/Makefile b/arch/arm64/boot/dts/Makefile
index 98ec8f1b76e4..fc726b215f12 100644
--- a/arch/arm64/boot/dts/Makefile
+++ b/arch/arm64/boot/dts/Makefile
@@ -9,6 +9,7 @@ subdir-y += amlogic
subdir-y += apm
subdir-y += apple
subdir-y += arm
+subdir-y += aspeed
subdir-y += axiado
subdir-y += bitmain
subdir-y += blaize
diff --git a/arch/arm64/boot/dts/aspeed/Makefile b/arch/arm64/boot/dts/aspeed/Makefile
new file mode 100644
index 000000000000..ffe7e15017cc
--- /dev/null
+++ b/arch/arm64/boot/dts/aspeed/Makefile
@@ -0,0 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0
+
+dtb-$(CONFIG_ARCH_ASPEED) += \
+ ast2700-evb.dtb
diff --git a/arch/arm64/boot/dts/aspeed/aspeed-evb-flash-layout-128.dtsi b/arch/arm64/boot/dts/aspeed/aspeed-evb-flash-layout-128.dtsi
new file mode 100644
index 000000000000..b54915f06efd
--- /dev/null
+++ b/arch/arm64/boot/dts/aspeed/aspeed-evb-flash-layout-128.dtsi
@@ -0,0 +1,32 @@
+// SPDX-License-Identifier: GPL-2.0-only OR MIT
+
+partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ u-boot@0 {
+ reg = <0x0 0x400000>; // 4MB
+ label = "u-boot";
+ };
+
+ u-boot-env@400000 {
+ reg = <0x400000 0x20000>; // 128KB
+ label = "u-boot-env";
+ };
+
+ kernel@420000 {
+ reg = <0x420000 0x900000>; // 9MB
+ label = "kernel";
+ };
+
+ rofs@d20000 {
+ reg = <0xd20000 0x52E0000>; // 82.875MB
+ label = "rofs";
+ };
+
+ rwfs@6000000 {
+ reg = <0x6000000 0x2000000>; // 32MB
+ label = "rwfs";
+ };
+};
diff --git a/arch/arm64/boot/dts/aspeed/aspeed-g7-a35.dtsi b/arch/arm64/boot/dts/aspeed/aspeed-g7-a35.dtsi
new file mode 100644
index 000000000000..ef283d95649a
--- /dev/null
+++ b/arch/arm64/boot/dts/aspeed/aspeed-g7-a35.dtsi
@@ -0,0 +1,196 @@
+// SPDX-License-Identifier: GPL-2.0-only OR MIT
+/*
+ * Device Tree Source for AST27xx SoC Family
+ *
+ * Copyright (C) 2026 ASPEED Technology Inc.
+ */
+
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+/ {
+ compatible = "aspeed,ast2700";
+ interrupt-parent = <&gic>;
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ cpus {
+ #address-cells = <2>;
+ #size-cells = <0>;
+
+ cpu0: cpu@0 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a35";
+ reg = <0x0 0x0>;
+ enable-method = "psci";
+ i-cache-size = <0x8000>;
+ i-cache-line-size = <64>;
+ i-cache-sets = <256>;
+ d-cache-size = <0x8000>;
+ d-cache-line-size = <64>;
+ d-cache-sets = <128>;
+ next-level-cache = <&l2>;
+ };
+
+ cpu1: cpu@1 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a35";
+ reg = <0x0 0x1>;
+ enable-method = "psci";
+ i-cache-size = <0x8000>;
+ i-cache-line-size = <64>;
+ i-cache-sets = <256>;
+ d-cache-size = <0x8000>;
+ d-cache-line-size = <64>;
+ d-cache-sets = <128>;
+ next-level-cache = <&l2>;
+ };
+
+ cpu2: cpu@2 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a35";
+ reg = <0x0 0x2>;
+ enable-method = "psci";
+ i-cache-size = <0x8000>;
+ i-cache-line-size = <64>;
+ i-cache-sets = <256>;
+ d-cache-size = <0x8000>;
+ d-cache-line-size = <64>;
+ d-cache-sets = <128>;
+ next-level-cache = <&l2>;
+ };
+
+ cpu3: cpu@3 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a35";
+ reg = <0x0 0x3>;
+ enable-method = "psci";
+ i-cache-size = <0x8000>;
+ i-cache-line-size = <64>;
+ i-cache-sets = <256>;
+ d-cache-size = <0x8000>;
+ d-cache-line-size = <64>;
+ d-cache-sets = <128>;
+ next-level-cache = <&l2>;
+ };
+
+ l2: l2-cache0 {
+ compatible = "cache";
+ cache-level = <2>;
+ cache-unified;
+ cache-size = <0x80000>;
+ cache-line-size = <64>;
+ cache-sets = <1024>;
+ };
+ };
+
+ secondary {
+ #address-cells = <2>;
+ /* https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/of/address.c?h=v6.16#n491 */
+ #size-cells = <0>;
+ /* https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/of/address.c?h=v6.16#n430 */
+
+ ssp_nvic: interrupt-controller@1,e000e100 {
+ compatible = "arm,v7m-nvic";
+ #interrupt-cells = <2>;
+ #address-cells = <0>;
+ interrupt-controller;
+ reg = <1 0xe000e100>;
+ arm,num-irq-priority-bits = <3>;
+ status = "disabled";
+ };
+ };
+
+ tertiary {
+ #address-cells = <2>;
+ #size-cells = <0>;
+
+ tsp_nvic: interrupt-controller@2,e000e100 {
+ compatible = "arm,v7m-nvic";
+ #interrupt-cells = <2>;
+ #address-cells = <0>;
+ interrupt-controller;
+ reg = <2 0xe000e100>;
+ arm,num-irq-priority-bits = <3>;
+ status = "disabled";
+ };
+ };
+
+ bootmcu {
+ bootmcu_hlic: interrupt-controller {
+ compatible = "riscv,cpu-intc";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ status = "disabled";
+ };
+ };
+
+ firmware {
+ optee: optee {
+ compatible = "linaro,optee-tz";
+ method = "smc";
+ };
+
+ psci {
+ compatible = "arm,psci-1.0";
+ method = "smc";
+ };
+ };
+
+ reserved-memory {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ atf: trusted-firmware-a@430000000 {
+ reg = <0x4 0x30000000 0x0 0x80000>;
+ no-map;
+ };
+
+ optee_core: optee-core@430080000 {
+ reg = <0x4 0x30080000 0x0 0x1000000>;
+ no-map;
+ };
+ };
+
+ arm-pmu {
+ compatible = "arm,cortex-a35-pmu";
+ interrupts = <GIC_PPI 7 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ timer {
+ compatible = "arm,armv8-timer";
+ interrupts = <GIC_PPI 13 IRQ_TYPE_LEVEL_LOW>,
+ <GIC_PPI 14 IRQ_TYPE_LEVEL_LOW>,
+ <GIC_PPI 11 IRQ_TYPE_LEVEL_LOW>,
+ <GIC_PPI 10 IRQ_TYPE_LEVEL_LOW>;
+ arm,cpu-registers-not-fw-configured;
+ always-on;
+ };
+
+ gic: interrupt-controller@12200000 {
+ compatible = "arm,gic-v3";
+ reg = <0 0x12200000 0 0x10000>, /* GICD */
+ <0 0x12280000 0 0x80000>, /* GICR */
+ <0 0x40440000 0 0x1000>; /* GICC */
+ interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_HIGH>;
+ #interrupt-cells = <3>;
+ interrupt-controller;
+ };
+
+ soc0: bus@10000000 {
+ compatible = "simple-bus";
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges = <0x0 0x10000000 0x0 0x10000000 0x0 0x4000000>;
+ };
+
+ soc1: bus@14000000 {
+ compatible = "simple-bus";
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges = <0x0 0x14000000 0x0 0x14000000 0x2 0xec000000>;
+ };
+};
+
+#include "aspeed-g7-soc0.dtsi"
+#include "aspeed-g7-soc1.dtsi"
diff --git a/arch/arm64/boot/dts/aspeed/aspeed-g7-soc0-pinctrl.dtsi b/arch/arm64/boot/dts/aspeed/aspeed-g7-soc0-pinctrl.dtsi
new file mode 100644
index 000000000000..ed58ee41973b
--- /dev/null
+++ b/arch/arm64/boot/dts/aspeed/aspeed-g7-soc0-pinctrl.dtsi
@@ -0,0 +1,225 @@
+// SPDX-License-Identifier: GPL-2.0-only OR MIT
+// Copyright 2025 ASPEED Corp.
+
+&pinctrl0 {
+ pinctrl_emmc_default: emmc-default-state {
+ function = "EMMC";
+ groups = "EMMCG1";
+ };
+ pinctrl_emmcg4_default: emmcg4-default-state {
+ function = "EMMC";
+ groups = "EMMCG4";
+ };
+ pinctrl_emmcg8_default: emmcg8-default-state {
+ function = "EMMC";
+ groups = "EMMCG8";
+ };
+ pinctrl_emmcwpn_default: emmcwpn-default-state {
+ function = "EMMC";
+ groups = "EMMCWPN";
+ };
+ pinctrl_emmccdn_default: emmccdn-default-state {
+ function = "EMMC";
+ groups = "EMMCCDN";
+ };
+ pinctrl_vb1_default: vb1-default-state {
+ function = "VB";
+ groups = "VB1";
+ };
+ pinctrl_vb0_default: vb0-default-state {
+ function = "VB";
+ groups = "VB0";
+ };
+ pinctrl_tsprstn_default: tsprstn-default-state {
+ function = "TSPRSTN";
+ groups = "TSPRSTN";
+ };
+ pinctrl_ufsclki_default: ufsclki-default-state {
+ function = "UFSCLKI";
+ groups = "UFSCLKI";
+ };
+ pinctrl_vgaddc_default: vgaddc-default-state {
+ function = "VGADDC";
+ groups = "VGADDC";
+ };
+ pinctrl_usb3axhd_default: usb3axhd-default-state {
+ function = "USB3AXHD";
+ groups = "USB3A";
+ };
+ pinctrl_usb3axhpd_default: usb3axhpd-default-state {
+ function = "USB3AXHPD";
+ groups = "USB3A";
+ };
+ pinctrl_usb3axh_default: usb3axh-default-state {
+ function = "USB3AXH";
+ groups = "USB3AAP";
+ };
+ pinctrl_usb3axhp_default: usb3axhp-default-state {
+ function = "USB3AXHP";
+ groups = "USB3AAP";
+ };
+ pinctrl_usb3axh2b_default: usb3axh2b-default-state {
+ function = "USB3AXH2B";
+ groups = "USB3ABP";
+ };
+ pinctrl_usb3axhp2b_default: usb3axhp2b-default-state {
+ function = "USB3AXHP2B";
+ groups = "USB3ABP";
+ };
+ pinctrl_usb2axhd1_default: usb2axhd1-default-state {
+ function = "USB2AXHD1";
+ groups = "USB2A";
+ };
+ pinctrl_usb2axhpd1_default: usb2axhpd1-default-state {
+ function = "USB2AXHPD1";
+ groups = "USB2A";
+ };
+ pinctrl_usb2ad1_default: usb2ad1-default-state {
+ function = "USB2AD1";
+ groups = "USB2ADAP";
+ };
+ pinctrl_usb2axh_default: usb2axh-default-state {
+ function = "USB2AXH";
+ groups = "USB2AAP";
+ };
+ pinctrl_usb2axhp_default: usb2axhp-default-state {
+ function = "USB2AXHP";
+ groups = "USB2AAP";
+ };
+ pinctrl_usb2axh2b_default: usb2axh2b-default-state {
+ function = "USB2AXH2B";
+ groups = "USB2ABP";
+ };
+ pinctrl_usb2axhp2b_default: usb2axhp2b-default-state {
+ function = "USB2AXHP2B";
+ groups = "USB2ABP";
+ };
+ pinctrl_usb2ahpd0_default: usb2ahpd0-default-state {
+ function = "USB2AHPD0";
+ groups = "USB2AH";
+ };
+ pinctrl_usb2ad0_default: usb2ad0-default-state {
+ function = "USB2AD0";
+ groups = "USB2AHAP";
+ };
+ pinctrl_usb2ah_default: usb2ah-default-state {
+ function = "USB2AH";
+ groups = "USB2AHAP";
+ };
+ pinctrl_usb2ahp_default: usb2ahp-default-state {
+ function = "USB2AHP";
+ groups = "USB2AHAP";
+ };
+ pinctrl_usb3bxhd_default: usb3bxhd-default-state {
+ function = "USB3BXHD";
+ groups = "USB3B";
+ };
+ pinctrl_usb3bxhpd_default: usb3bxhpd-default-state {
+ function = "USB3BXHPD";
+ groups = "USB3B";
+ };
+ pinctrl_usb3bxh_default: usb3bxh-default-state {
+ function = "USB3BXH";
+ groups = "USB3BBP";
+ };
+ pinctrl_usb3bxhp_default: usb3bxhp-default-state {
+ function = "USB3BXHP";
+ groups = "USB3BBP";
+ };
+ pinctrl_usb3bxh2a_default: usb3bxh2a-default-state {
+ function = "USB3BXH2A";
+ groups = "USB3BAP";
+ };
+ pinctrl_usb3bxhp2a_default: usb3bxhp2a-default-state {
+ function = "USB3BXHP2A";
+ groups = "USB3BAP";
+ };
+ pinctrl_usb2bxhd1_default: usb2bxhd1-default-state {
+ function = "USB2BXHD1";
+ groups = "USB2B";
+ };
+ pinctrl_usb2bxhpd1_default: usb2bxhpd1-default-state {
+ function = "USB2BXHPD1";
+ groups = "USB2B";
+ };
+ pinctrl_usb2bd1_default: usb2bd1-default-state {
+ function = "USB2BD1";
+ groups = "USB2BDBP";
+ };
+ pinctrl_usb2bxh_default: usb2bxh-default-state {
+ function = "USB2BXH";
+ groups = "USB2BBP";
+ };
+ pinctrl_usb2bxhp_default: usb2bxhp-default-state {
+ function = "USB2BXHP";
+ groups = "USB2BBP";
+ };
+ pinctrl_usb2bxh2a_default: usb2bxh2a-default-state {
+ function = "USB2BXH2A";
+ groups = "USB2BAP";
+ };
+ pinctrl_usb2bxhp2a_default: usb2bxhp2a-default-state {
+ function = "USB2BXHP2A";
+ groups = "USB2BAP";
+ };
+ pinctrl_usb2bhpd0_default: usb2bhpd0-default-state {
+ function = "USB2BHPD0";
+ groups = "USB2BH";
+ };
+ pinctrl_usb2bd0_default: usb2bd0-default-state {
+ function = "USB2BD0";
+ groups = "USB2BHBP";
+ };
+ pinctrl_usb2bh_default: usb2bh-default-state {
+ function = "USB2BH";
+ groups = "USB2BHBP";
+ };
+ pinctrl_usb2bhp_default: usb2bhp-default-state {
+ function = "USB2BHP";
+ groups = "USB2BHBP";
+ };
+ pinctrl_jtagm0_default: jtagm0-default-state {
+ function = "JTAGM0";
+ groups = "JTAG0";
+ };
+ pinctrl_jtag_psp_default: jtag-psp-default-state {
+ function = "JTAGPSP";
+ groups = "JTAG0";
+ };
+ pinctrl_jtag_ssp_default: jtag-ssp-default-state {
+ function = "JTAGSSP";
+ groups = "JTAG0";
+ };
+ pinctrl_jtag_tsp_default: jtag-tsp-default-state {
+ function = "JTAGTSP";
+ groups = "JTAG0";
+ };
+ pinctrl_jtag_ddr_default: jtag-ddr-default-state {
+ function = "JTAGDDR";
+ groups = "JTAG0";
+ };
+ pinctrl_jtag_usb3a_default: jtag-usb3a-default-state {
+ function = "JTAGUSB3A";
+ groups = "JTAG0";
+ };
+ pinctrl_jtag_usb3b_default: jtag-usb3b-default-state {
+ function = "JTAGUSB3B";
+ groups = "JTAG0";
+ };
+ pinctrl_jtag_pciea_default: jtag-pciea-default-state {
+ function = "JTAGPCIEA";
+ groups = "JTAG0";
+ };
+ pinctrl_jtag_pcieb_default: jtag-pcieb-default-state {
+ function = "JTAGPCIEB";
+ groups = "JTAG0";
+ };
+ pinctrl_pcierc0_perst_default: pcierc0-perst-default-state {
+ function = "PCIERC0PERST";
+ groups = "PCIERC0PERST";
+ };
+ pinctrl_pcierc1_perst_default: pcierc1-perst-default-state {
+ function = "PCIERC1PERST";
+ groups = "PCIERC1PERST";
+ };
+};
diff --git a/arch/arm64/boot/dts/aspeed/aspeed-g7-soc0.dtsi b/arch/arm64/boot/dts/aspeed/aspeed-g7-soc0.dtsi
new file mode 100644
index 000000000000..db42db2592e0
--- /dev/null
+++ b/arch/arm64/boot/dts/aspeed/aspeed-g7-soc0.dtsi
@@ -0,0 +1,230 @@
+// SPDX-License-Identifier: GPL-2.0-only OR MIT
+/*
+ * Device Tree Source for AST27xx SoC Family Main Domain peripherals
+ *
+ * Copyright (C) 2026 ASPEED Technology Inc.
+ */
+
+#include <dt-bindings/clock/aspeed,ast2700-scu.h>
+#include <dt-bindings/reset/aspeed,ast2700-scu.h>
+#include <dt-bindings/interrupt-controller/aspeed-scu-ic.h>
+
+&soc0 {
+ sram0: sram@10000000 {
+ compatible = "mmio-sram";
+ reg = <0x0 0x10000000 0x0 0x20000>;
+ ranges = <0x0 0x0 0x10000000 0x20000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ soc0-sram@0 {
+ reg = <0x0 0x20000>;
+ export;
+ };
+ };
+
+ vhuba1: usb-vhub@12011000 {
+ compatible = "aspeed,ast2700-usb-vhub";
+ reg = <0x0 0x12011000 0x0 0x820>;
+ interrupts-extended = <&intc0 32>;
+ clocks = <&syscon0 SCU0_CLK_GATE_PORTAUSB2CLK>;
+ resets = <&syscon0 SCU0_RESET_PORTA_VHUB>;
+ aspeed,vhub-downstream-ports = <7>;
+ aspeed,vhub-generic-endpoints = <21>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usb2axhpd1_default>;
+ status = "disabled";
+ };
+
+ vhubb1: usb-vhub@12021000 {
+ compatible = "aspeed,ast2700-usb-vhub";
+ reg = <0x0 0x12021000 0x0 0x820>;
+ interrupts-extended = <&intc0 36>;
+ clocks = <&syscon0 SCU0_CLK_GATE_PORTBUSB2CLK>;
+ resets = <&syscon0 SCU0_RESET_PORTB_VHUB>;
+ aspeed,vhub-downstream-ports = <7>;
+ aspeed,vhub-generic-endpoints = <21>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usb2bxhpd1_default>;
+ status = "disabled";
+ };
+
+ uhci0: usb@12040000 {
+ compatible = "aspeed,ast2700-uhci", "generic-uhci";
+ reg = <0x0 0x12040000 0x0 0x100>;
+ interrupts-extended = <&intc0 10>;
+ #ports = <2>;
+ clocks = <&syscon0 SCU0_CLK_GATE_UHCICLK>;
+ resets = <&syscon0 SCU0_RESET_UHCI>;
+ status = "disabled";
+ };
+
+ vhuba0: usb-vhub@12060000 {
+ compatible = "aspeed,ast2700-usb-vhub";
+ reg = <0x0 0x12060000 0x0 0x820>;
+ interrupts-extended = <&intc0 33>;
+ clocks = <&syscon0 SCU0_CLK_GATE_PORTAUSB2CLK>;
+ resets = <&syscon0 SCU0_RESET_PORTA_VHUB_EHCI>;
+ aspeed,vhub-downstream-ports = <7>;
+ aspeed,vhub-generic-endpoints = <21>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usb2ad0_default>;
+ status = "disabled";
+ };
+
+ ehci0: usb@12061000 {
+ compatible = "aspeed,ast2700-ehci", "generic-ehci";
+ reg = <0x0 0x12061000 0x0 0x100>;
+ interrupts-extended = <&intc0 33>;
+ clocks = <&syscon0 SCU0_CLK_GATE_PORTAUSB2CLK>;
+ resets = <&syscon0 SCU0_RESET_PORTA_VHUB_EHCI>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usb2ah_default>;
+ status = "disabled";
+ };
+
+ vhubb0: usb-vhub@12062000 {
+ compatible = "aspeed,ast2700-usb-vhub";
+ reg = <0x0 0x12062000 0x0 0x820>;
+ interrupts-extended = <&intc0 37>;
+ clocks = <&syscon0 SCU0_CLK_GATE_PORTBUSB2CLK>;
+ resets = <&syscon0 SCU0_RESET_PORTB_VHUB_EHCI>;
+ aspeed,vhub-downstream-ports = <7>;
+ aspeed,vhub-generic-endpoints = <21>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usb2bd0_default>;
+ status = "disabled";
+ };
+
+ ehci1: usb@12063000 {
+ compatible = "aspeed,ast2700-ehci", "generic-ehci";
+ reg = <0x0 0x12063000 0x0 0x100>;
+ interrupts-extended = <&intc0 37>;
+ clocks = <&syscon0 SCU0_CLK_GATE_PORTBUSB2CLK>;
+ resets = <&syscon0 SCU0_RESET_PORTB_VHUB_EHCI>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usb2bh_default>;
+ status = "disabled";
+ };
+
+ emmc_controller: sdc@12090000 {
+ compatible = "aspeed,ast2700-sd-controller", "aspeed,ast2600-sd-controller";
+ reg = <0 0x12090000 0 0x100>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0x0 0x0 0x12090000 0x10000>;
+ clocks = <&syscon0 SCU0_CLK_GATE_EMMCCLK>;
+ resets = <&syscon0 SCU0_RESET_EMMC>;
+ status = "disabled";
+
+ emmc: sdhci@100 {
+ compatible = "aspeed,ast2700-sdhci", "aspeed,ast2600-sdhci";
+ reg = <0x100 0x100>;
+ sdhci,auto-cmd12;
+ interrupts-extended = <&intc0 15>;
+ clocks = <&syscon0 SCU0_CLK_GATE_EMMCCLK>;
+ status = "disabled";
+ };
+ };
+
+ intc0: interrupt-controller@12100000 {
+ compatible = "aspeed,ast2700-intc0";
+ reg = <0x0 0x12100000 0x0 0x3c00>;
+ interrupt-controller;
+ interrupt-parent = <&gic>;
+ #interrupt-cells = <1>;
+ aspeed,interrupt-ranges =
+ <0 128 &gic GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>, /* linear range 1 to 1*/
+ <144 8 &gic GIC_SPI 144 IRQ_TYPE_LEVEL_HIGH>, /* sw int SSP */
+ <152 8 &gic GIC_SPI 152 IRQ_TYPE_LEVEL_HIGH>, /* sw int TSP */
+ <192 10 &gic GIC_SPI 192 IRQ_TYPE_LEVEL_HIGH>, /* M0-M9 intm */
+ <208 10 &gic GIC_SPI 208 IRQ_TYPE_LEVEL_HIGH>, /* M30-M39 intm */
+ <224 10 &gic GIC_SPI 224 IRQ_TYPE_LEVEL_HIGH>, /* M40-M49 intm */
+ <256 128 &ssp_nvic 0 0 >, /* linear to SSP */
+ <384 10 &ssp_nvic 160 0 >, /* cascaded to SSP via M10-M19 */
+ <400 8 &ssp_nvic 144 0 >, /* sw int PSP */
+ <408 8 &ssp_nvic 152 0 >, /* sw int TSP */
+ <426 128 &tsp_nvic 0 0 >, /* linear to TSP */
+ <554 10 &tsp_nvic 160 0 >, /* cascaded to TSP via M20-M29 */
+ <570 8 &tsp_nvic 144 0 >, /* sw int PSP */
+ <578 8 &tsp_nvic 152 0 >; /* sw int TSP */
+ };
+
+ syscon0: syscon@12c02000 {
+ compatible = "aspeed,ast2700-scu0", "syscon", "simple-mfd";
+ reg = <0x0 0x12c02000 0x0 0x1000>;
+ ranges = <0x0 0x0 0x12c02000 0x1000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+
+ silicon-id@0 {
+ compatible = "aspeed,ast2700-silicon-id", "aspeed,silicon-id";
+ reg = <0x0 0x4>;
+ };
+
+ scu_ic0: interrupt-controller@1d0 {
+ compatible = "aspeed,ast2700-scu-ic0";
+ reg = <0x1d0 0xc>;
+ interrupts-extended = <&intc0 97>;
+ #interrupt-cells = <1>;
+ interrupt-controller;
+ };
+
+ scu_ic1: interrupt-controller@1e0 {
+ compatible = "aspeed,ast2700-scu-ic1";
+ reg = <0x1e0 0xc>;
+ interrupts-extended = <&intc0 98>;
+ #interrupt-cells = <1>;
+ interrupt-controller;
+ };
+
+ pinctrl0: pinctrl@400 {
+ compatible = "aspeed,ast2700-soc0-pinctrl";
+ reg = <0x400 0x318>;
+ };
+ };
+
+ gpio0: gpio@12c11000 {
+ #gpio-cells = <2>;
+ gpio-controller;
+ compatible = "aspeed,ast2700-gpio";
+ reg = <0x0 0x12c11000 0x0 0x1000>;
+ interrupts-extended = <&intc0 11>;
+ gpio-ranges = <&pinctrl0 0 0 12>;
+ ngpios = <12>;
+ clocks = <&syscon0 SCU0_CLK_APB>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ uart4: serial@12c1a000 {
+ compatible = "ns16550a";
+ reg = <0x0 0x12c1a000 0x0 0x1000>;
+ reg-shift = <2>;
+ reg-io-width = <4>;
+ clocks = <&syscon0 SCU0_CLK_GATE_UART4CLK>;
+ interrupts-extended = <&intc0 8>;
+ no-loopback-test;
+ status = "disabled";
+ };
+
+ mbox0: mbox@12c1c200 {
+ compatible = "aspeed,ast2700-mailbox";
+ reg = <0x0 0x12c1c200 0x0 0x100>, <0x0 0x12c1c300 0x0 0x100>;
+ reg-names = "tx", "rx";
+ interrupts-extended = <&intc0 103>;
+ #mbox-cells = <1>;
+ };
+
+ mbox1: mbox@12c1c600 {
+ compatible = "aspeed,ast2700-mailbox";
+ reg = <0x0 0x12c1c600 0x0 0x100>, <0x0 0x12c1c700 0x0 0x100>;
+ reg-names = "tx", "rx";
+ interrupts-extended = <&intc0 107>;
+ #mbox-cells = <1>;
+ };
+};
+
+#include "aspeed-g7-soc0-pinctrl.dtsi"
diff --git a/arch/arm64/boot/dts/aspeed/aspeed-g7-soc1-pinctrl.dtsi b/arch/arm64/boot/dts/aspeed/aspeed-g7-soc1-pinctrl.dtsi
new file mode 100644
index 000000000000..72d93323593d
--- /dev/null
+++ b/arch/arm64/boot/dts/aspeed/aspeed-g7-soc1-pinctrl.dtsi
@@ -0,0 +1,1113 @@
+// SPDX-License-Identifier: GPL-2.0-only OR MIT
+// Copyright 2025 ASPEED Corp.
+
+&pinctrl1 {
+ pinctrl_sgpm0_default: sgpm0-default-state {
+ function = "SGPM0";
+ groups = "SGPM0";
+ };
+
+ pinctrl_dsgpm0_default: dsgpm0-default-state {
+ function = "SGPM0";
+ groups = "DSGPM0";
+ };
+
+ pinctrl_sgpm1_default: sgpm1-default-state {
+ function = "SGPM1";
+ groups = "SGPM1";
+ };
+
+ pinctrl_sgps_default: sgps-default-state {
+ function = "SGPS";
+ groups = "SGPS";
+ };
+
+ pinctrl_adc0_default: adc0-default-state {
+ function = "ADC0";
+ groups = "ADC0";
+ };
+
+ pinctrl_adc1_default: adc1-default-state {
+ function = "ADC1";
+ groups = "ADC1";
+ };
+
+ pinctrl_adc2_default: adc2-default-state {
+ function = "ADC2";
+ groups = "ADC2";
+ };
+
+ pinctrl_adc3_default: adc3-default-state {
+ function = "ADC3";
+ groups = "ADC3";
+ };
+
+ pinctrl_adc4_default: adc4-default-state {
+ function = "ADC4";
+ groups = "ADC4";
+ };
+
+ pinctrl_adc5_default: adc5-default-state {
+ function = "ADC5";
+ groups = "ADC5";
+ };
+
+ pinctrl_adc6_default: adc6-default-state {
+ function = "ADC6";
+ groups = "ADC6";
+ };
+
+ pinctrl_adc7_default: adc7-default-state {
+ function = "ADC7";
+ groups = "ADC7";
+ };
+
+ pinctrl_adc8_default: adc8-default-state {
+ function = "ADC8";
+ groups = "ADC8";
+ };
+
+ pinctrl_adc9_default: adc9-default-state {
+ function = "ADC9";
+ groups = "ADC9";
+ };
+
+ pinctrl_adc10_default: adc10-default-state {
+ function = "ADC10";
+ groups = "ADC10";
+ };
+
+ pinctrl_adc11_default: adc11-default-state {
+ function = "ADC11";
+ groups = "ADC11";
+ };
+
+ pinctrl_adc12_default: adc12-default-state {
+ function = "ADC12";
+ groups = "ADC12";
+ };
+
+ pinctrl_adc13_default: adc13-default-state {
+ function = "ADC13";
+ groups = "ADC13";
+ };
+
+ pinctrl_adc14_default: adc14-default-state {
+ function = "ADC14";
+ groups = "ADC14";
+ };
+
+ pinctrl_adc15_default: adc15-default-state {
+ function = "ADC15";
+ groups = "ADC15";
+ };
+
+ pinctrl_pwm0_default: pwm0-default-state {
+ function = "PWM0";
+ groups = "PWM0";
+ };
+
+ pinctrl_pwm1_default: pwm1-default-state {
+ function = "PWM1";
+ groups = "PWM1";
+ };
+
+ pinctrl_pwm2_default: pwm2-default-state {
+ function = "PWM2";
+ groups = "PWM2";
+ };
+
+ pinctrl_pwm3_default: pwm3-default-state {
+ function = "PWM3";
+ groups = "PWM3";
+ };
+
+ pinctrl_pwm4_default: pwm4-default-state {
+ function = "PWM4";
+ groups = "PWM4";
+ };
+
+ pinctrl_pwm5_default: pwm5-default-state {
+ function = "PWM5";
+ groups = "PWM5";
+ };
+
+ pinctrl_pwm6_default: pwm6-default-state {
+ function = "PWM6";
+ groups = "PWM6";
+ };
+
+ pinctrl_pwm7_default: pwm7-default-state {
+ function = "PWM7";
+ groups = "PWM7";
+ };
+
+ pinctrl_pwm8_default: pwm8-default-state {
+ function = "PWM8";
+ groups = "PWM8";
+ };
+
+ pinctrl_pwm9_default: pwm9-default-state {
+ function = "PWM9";
+ groups = "PWM9";
+ };
+
+ pinctrl_pwm10_default: pwm10-default-state {
+ function = "PWM10";
+ groups = "PWM10";
+ };
+
+ pinctrl_pwm11_default: pwm11-default-state {
+ function = "PWM11";
+ groups = "PWM11";
+ };
+
+ pinctrl_pwm12_default: pwm12-default-state {
+ function = "PWM12";
+ groups = "PWM12";
+ };
+
+ pinctrl_pwm13_default: pwm13-default-state {
+ function = "PWM13";
+ groups = "PWM13";
+ };
+
+ pinctrl_pwm14_default: pwm14-default-state {
+ function = "PWM14";
+ groups = "PWM14";
+ };
+
+ pinctrl_pwm15_default: pwm15-default-state {
+ function = "PWM15";
+ groups = "PWM15";
+ };
+
+ pinctrl_tach0_default: tach0-default-state {
+ function = "TACH0";
+ groups = "TACH0";
+ };
+
+ pinctrl_tach1_default: tach1-default-state {
+ function = "TACH1";
+ groups = "TACH1";
+ };
+
+ pinctrl_tach2_default: tach2-default-state {
+ function = "TACH2";
+ groups = "TACH2";
+ };
+
+ pinctrl_tach3_default: tach3-default-state {
+ function = "TACH3";
+ groups = "TACH3";
+ };
+
+ pinctrl_tach4_default: tach4-default-state {
+ function = "TACH4";
+ groups = "TACH4";
+ };
+
+ pinctrl_tach5_default: tach5-default-state {
+ function = "TACH5";
+ groups = "TACH5";
+ };
+
+ pinctrl_tach6_default: tach6-default-state {
+ function = "TACH6";
+ groups = "TACH6";
+ };
+
+ pinctrl_tach7_default: tach7-default-state {
+ function = "TACH7";
+ groups = "TACH7";
+ };
+
+ pinctrl_tach8_default: tach8-default-state {
+ function = "TACH8";
+ groups = "TACH8";
+ };
+
+ pinctrl_tach9_default: tach9-default-state {
+ function = "TACH9";
+ groups = "TACH9";
+ };
+
+ pinctrl_tach10_default: tach10-default-state {
+ function = "TACH10";
+ groups = "TACH10";
+ };
+
+ pinctrl_tach11_default: tach11-default-state {
+ function = "TACH11";
+ groups = "TACH11";
+ };
+
+ pinctrl_tach12_default: tach12-default-state {
+ function = "TACH12";
+ groups = "TACH12";
+ };
+
+ pinctrl_tach13_default: tach13-default-state {
+ function = "TACH13";
+ groups = "TACH13";
+ };
+
+ pinctrl_tach14_default: tach14-default-state {
+ function = "TACH14";
+ groups = "TACH14";
+ };
+
+ pinctrl_tach15_default: tach15-default-state {
+ function = "TACH15";
+ groups = "TACH15";
+ };
+
+ pinctrl_jtagm1_default: jtagm1-default-state {
+ function = "JTAGM1";
+ groups = "JTAGM1";
+ };
+
+ pinctrl_mdio0_default: mdio0-default-state {
+ function = "MDIO0";
+ groups = "MDIO0";
+ };
+
+ pinctrl_mdio1_default: mdio1-default-state {
+ function = "MDIO1";
+ groups = "MDIO1";
+ };
+
+ pinctrl_mdio2_default: mdio2-default-state {
+ function = "MDIO2";
+ groups = "MDIO2";
+ };
+
+ pinctrl_rgmii0_default: rgmii0-default-state {
+ function = "RGMII0";
+ groups = "RGMII0";
+ };
+
+ pinctrl_rgmii1_default: rgmii1-default-state {
+ function = "RGMII1";
+ groups = "RGMII1";
+ };
+
+ pinctrl_rmii0_default: rmii0-default-state {
+ function = "RMII0";
+ groups = "RMII0";
+ };
+
+ pinctrl_rmii0_rclko_default: rmii0-rclko-default-state {
+ function = "RMII0RCLKO";
+ groups = "RMII0RCLKO";
+ };
+
+ pinctrl_rmii1_default: rmii1-default-state {
+ function = "RMII1";
+ groups = "RMII1";
+ };
+
+ pinctrl_rmii1_rclko_default: rmii1-rclko-default-state {
+ function = "RMII1RCLKO";
+ groups = "RMII1RCLKO";
+ };
+
+ pinctrl_sgmii_default: sgmii-default-state {
+ function = "SGMII";
+ groups = "SGMII";
+ };
+
+ pinctrl_fwspi_quad_default: fwspi-quad-default-state {
+ function = "FWQSPI";
+ groups = "FWQSPI";
+ };
+
+ pinctrl_fsi0_default: fsi0-default-state {
+ function = "FSI0";
+ groups = "FSI0";
+ };
+
+ pinctrl_fsi1_default: fsi1-default-state {
+ function = "FSI1";
+ groups = "FSI1";
+ };
+
+ pinctrl_fsi2_default: fsi2-default-state {
+ function = "FSI2";
+ groups = "FSI2";
+ };
+
+ pinctrl_fsi3_default: fsi3-default-state {
+ function = "FSI3";
+ groups = "FSI3";
+ };
+
+ pinctrl_spi0_default: spi0-default-state {
+ function = "SPI0";
+ groups = "SPI0";
+ };
+
+ pinctrl_spi0_quad_default: spi0-quad-default-state {
+ function = "QSPI0";
+ groups = "QSPI0";
+ };
+
+ pinctrl_spi0_cs1_default: spi0-cs1-default-state {
+ function = "SPI0CS1";
+ groups = "SPI0CS1";
+ };
+
+ pinctrl_spi1_default: spi1-default-state {
+ function = "SPI1";
+ groups = "SPI1";
+ };
+
+ pinctrl_spi1_quad_default: spi1-quad-default-state {
+ function = "QSPI1";
+ groups = "QSPI1";
+ };
+
+ pinctrl_spi1_cs1_default: spi1-cs1-default-state {
+ function = "SPI1CS1";
+ groups = "SPI1CS1";
+ };
+
+ pinctrl_spi2_default: spi2-default-state {
+ function = "SPI2";
+ groups = "SPI2";
+ };
+
+ pinctrl_spi2_quad_default: spi2-quad-default-state {
+ function = "QSPI2";
+ groups = "QSPI2";
+ };
+
+ pinctrl_spi2_cs1_default: spi2-cs1-default-state {
+ function = "SPI2CS1";
+ groups = "SPI2CS1";
+ };
+
+ pinctrl_espi0_default: espi0-default-state {
+ function = "ESPI0";
+ groups = "ESPI0";
+ };
+
+ pinctrl_espi1_default: espi1-default-state {
+ function = "ESPI1";
+ groups = "ESPI1";
+ };
+
+ pinctrl_lpc0_default: lpc0-default-state {
+ function = "LPC0";
+ groups = "LPC0";
+ };
+
+ pinctrl_lpc1_default: lpc1-default-state {
+ function = "LPC1";
+ groups = "LPC1";
+ };
+
+ pinctrl_vpi_default: vpi-default-state {
+ function = "VPI";
+ groups = "VPI";
+ };
+
+ pinctrl_sd_default: sd-default-state {
+ function = "SD";
+ groups = "SD";
+ };
+
+ pinctrl_hvi3c0_default: hvi3c0-default-state {
+ function = "I3C0";
+ groups = "HVI3C0";
+ };
+
+ pinctrl_hvi3c1_default: hvi3c1-default-state {
+ function = "I3C1";
+ groups = "HVI3C1";
+ };
+
+ pinctrl_hvi3c2_default: hvi3c2-default-state {
+ function = "I3C2";
+ groups = "HVI3C2";
+ };
+
+ pinctrl_hvi3c3_default: hvi3c3-default-state {
+ function = "I3C3";
+ groups = "HVI3C3";
+ };
+
+ pinctrl_i3c4_default: i3c4-default-state {
+ function = "I3C4";
+ groups = "I3C4";
+ };
+
+ pinctrl_i3c5_default: i3c5-default-state {
+ function = "I3C5";
+ groups = "I3C5";
+ };
+
+ pinctrl_i3c6_default: i3c6-default-state {
+ function = "I3C6";
+ groups = "I3C6";
+ };
+
+ pinctrl_i3c7_default: i3c7-default-state {
+ function = "I3C7";
+ groups = "I3C7";
+ };
+
+ pinctrl_i3c8_default: i3c8-default-state {
+ function = "I3C8";
+ groups = "I3C8";
+ };
+
+ pinctrl_i3c9_default: i3c9-default-state {
+ function = "I3C9";
+ groups = "I3C9";
+ };
+
+ pinctrl_i3c10_default: i3c10-default-state {
+ function = "I3C10";
+ groups = "I3C10";
+ };
+
+ pinctrl_i3c11_default: i3c11-default-state {
+ function = "I3C11";
+ groups = "I3C11";
+ };
+
+ pinctrl_hvi3c12_default: hvi3c12-default-state {
+ function = "I3C12";
+ groups = "HVI3C12";
+ };
+
+ pinctrl_hvi3c13_default: hvi3c13-default-state {
+ function = "I3C13";
+ groups = "HVI3C13";
+ };
+
+ pinctrl_hvi3c14_default: hvi3c14-default-state {
+ function = "I3C14";
+ groups = "HVI3C14";
+ };
+
+ pinctrl_hvi3c15_default: hvi3c15-default-state {
+ function = "I3C15";
+ groups = "HVI3C15";
+ };
+
+ pinctrl_tach0_default: tach0-default-state {
+ function = "TACH0";
+ groups = "TACH0";
+ };
+
+ pinctrl_tach1_default: tach1-default-state {
+ function = "TACH1";
+ groups = "TACH1";
+ };
+
+ pinctrl_tach2_default: tach2-default-state {
+ function = "TACH2";
+ groups = "TACH2";
+ };
+
+ pinctrl_tach3_default: tach3-default-state {
+ function = "TACH3";
+ groups = "TACH3";
+ };
+
+ pinctrl_tach4_default: tach4-default-state {
+ function = "TACH4";
+ groups = "TACH4";
+ };
+
+ pinctrl_tach5_default: tach5-default-state {
+ function = "TACH5";
+ groups = "TACH5";
+ };
+
+ pinctrl_tach6_default: tach6-default-state {
+ function = "TACH6";
+ groups = "TACH6";
+ };
+
+ pinctrl_tach7_default: tach7-default-state {
+ function = "TACH7";
+ groups = "TACH7";
+ };
+
+ pinctrl_tach8_default: tach8-default-state {
+ function = "TACH8";
+ groups = "TACH8";
+ };
+
+ pinctrl_tach9_default: tach9-default-state {
+ function = "TACH9";
+ groups = "TACH9";
+ };
+
+ pinctrl_tach10_default: tach10-default-state {
+ function = "TACH10";
+ groups = "TACH10";
+ };
+
+ pinctrl_tach11_default: tach11-default-state {
+ function = "TACH11";
+ groups = "TACH11";
+ };
+
+ pinctrl_tach12_default: tach12-default-state {
+ function = "TACH12";
+ groups = "TACH12";
+ };
+
+ pinctrl_tach13_default: tach13-default-state {
+ function = "TACH13";
+ groups = "TACH13";
+ };
+
+ pinctrl_tach14_default: tach14-default-state {
+ function = "TACH14";
+ groups = "TACH14";
+ };
+
+ pinctrl_tach15_default: tach15-default-state {
+ function = "TACH15";
+ groups = "TACH15";
+ };
+
+ pinctrl_thru0_default: thru0-default-state {
+ function = "THRU0";
+ groups = "THRU0";
+ };
+
+ pinctrl_thru1_default: thru1-default-state {
+ function = "THRU1";
+ groups = "THRU1";
+ };
+
+ pinctrl_thru2_default: thru2-default-state {
+ function = "THRU2";
+ groups = "THRU2";
+ };
+
+ pinctrl_thru3_default: thru3-default-state {
+ function = "THRU3";
+ groups = "THRU3";
+ };
+
+ pinctrl_ncts5_default: ncts5-default-state {
+ function = "NCTS5";
+ groups = "NCTS5";
+ };
+
+ pinctrl_ndcd5_default: ndcd5-default-state {
+ function = "NDCD5";
+ groups = "NDCD5";
+ };
+
+ pinctrl_ndsr5_default: ndsr5-default-state {
+ function = "NDSR5";
+ groups = "NDSR5";
+ };
+
+ pinctrl_nri5_default: nri5-default-state {
+ function = "NRI5";
+ groups = "NRI5";
+ };
+
+ pinctrl_i2c0_default: i2c0-default-state {
+ function = "I2C0";
+ groups = "I2C0";
+ };
+
+ pinctrl_i2c1_default: i2c1-default-state {
+ function = "I2C1";
+ groups = "I2C1";
+ };
+
+ pinctrl_i2c2_default: i2c2-default-state {
+ function = "I2C2";
+ groups = "I2C2";
+ };
+
+ pinctrl_i2c3_default: i2c3-default-state {
+ function = "I2C3";
+ groups = "I2C3";
+ };
+
+ pinctrl_i2c4_default: i2c4-default-state {
+ function = "I2C4";
+ groups = "I2C4";
+ };
+
+ pinctrl_i2c5_default: i2c5-default-state {
+ function = "I2C5";
+ groups = "I2C5";
+ };
+
+ pinctrl_i2c6_default: i2c6-default-state {
+ function = "I2C6";
+ groups = "I2C6";
+ };
+
+ pinctrl_i2c7_default: i2c7-default-state {
+ function = "I2C7";
+ groups = "I2C7";
+ };
+
+ pinctrl_i2c8_default: i2c8-default-state {
+ function = "I2C8";
+ groups = "I2C8";
+ };
+
+ pinctrl_i2c9_default: i2c9-default-state {
+ function = "I2C9";
+ groups = "I2C9";
+ };
+
+ pinctrl_i2c10_default: i2c10-default-state {
+ function = "I2C10";
+ groups = "I2C10";
+ };
+
+ pinctrl_i2c11_default: i2c11-default-state {
+ function = "I2C11";
+ groups = "I2C11";
+ };
+
+ pinctrl_i2c12_default: i2c12-default-state {
+ function = "I2C12";
+ groups = "I2C12";
+ };
+
+ pinctrl_i2c13_default: i2c13-default-state {
+ function = "I2C13";
+ groups = "I2C13";
+ };
+
+ pinctrl_i2c14_default: i2c14-default-state {
+ function = "I2C14";
+ groups = "I2C14";
+ };
+
+ pinctrl_i2c15_default: i2c15-default-state {
+ function = "I2C15";
+ groups = "I2C15";
+ };
+
+ pinctrl_salt0_default: salt0-default-state {
+ function = "SALT0";
+ groups = "SALT0";
+ };
+
+ pinctrl_salt1_default: salt1-default-state {
+ function = "SALT1";
+ groups = "SALT1";
+ };
+
+ pinctrl_salt2_default: salt2-default-state {
+ function = "SALT2";
+ groups = "SALT2";
+ };
+
+ pinctrl_salt3_default: salt3-default-state {
+ function = "SALT3";
+ groups = "SALT3";
+ };
+
+ pinctrl_salt4_default: salt4-default-state {
+ function = "SALT4";
+ groups = "SALT4";
+ };
+
+ pinctrl_salt5_default: salt5-default-state {
+ function = "SALT5";
+ groups = "SALT5";
+ };
+
+ pinctrl_salt6_default: salt6-default-state {
+ function = "SALT6";
+ groups = "SALT6";
+ };
+
+ pinctrl_salt7_default: salt7-default-state {
+ function = "SALT7";
+ groups = "SALT7";
+ };
+
+ pinctrl_salt8_default: salt8-default-state {
+ function = "SALT8";
+ groups = "SALT8";
+ };
+
+ pinctrl_salt9_default: salt9-default-state {
+ function = "SALT9";
+ groups = "SALT9";
+ };
+
+ pinctrl_salt10_default: salt10-default-state {
+ function = "SALT10";
+ groups = "SALT10";
+ };
+
+ pinctrl_salt11_default: salt11-default-state {
+ function = "SALT11";
+ groups = "SALT11";
+ };
+
+ pinctrl_salt12_default: salt12-default-state {
+ function = "SALT12";
+ groups = "SALT12";
+ };
+
+ pinctrl_salt13_default: salt13-default-state {
+ function = "SALT13";
+ groups = "SALT13";
+ };
+
+ pinctrl_salt14_default: salt14-default-state {
+ function = "SALT14";
+ groups = "SALT14";
+ };
+
+ pinctrl_salt15_default: salt15-default-state {
+ function = "SALT15";
+ groups = "SALT15";
+ };
+
+ pinctrl_ltpipsi2c0_default: ltpipsi2c0-default-state {
+ function = "I2C0";
+ groups = "LTPI_PS_I2C0";
+ };
+
+ pinctrl_ltpipsi2c1_default: ltpipsi2c1-default-state {
+ function = "I2C1";
+ groups = "LTPI_PS_I2C1";
+ };
+
+ pinctrl_ltpipsi2c2_default: ltpipsi2c2-default-state {
+ function = "I2C2";
+ groups = "LTPI_PS_I2C2";
+ };
+
+ pinctrl_ltpipsi2c3_default: ltpipsi2c3-default-state {
+ function = "I2C3";
+ groups = "LTPI_PS_I2C3";
+ };
+
+ pinctrl_can_default: can-default-state {
+ function = "CANBUS";
+ groups = "CANBUS";
+ };
+
+ pinctrl_di2c0_default: di2c0-default-state {
+ function = "I2C0";
+ groups = "DI2C0";
+ };
+
+ pinctrl_di2c1_default: di2c1-default-state {
+ function = "I2C1";
+ groups = "DI2C1";
+ };
+
+ pinctrl_di2c2_default: di2c2-default-state {
+ function = "I2C2";
+ groups = "DI2C2";
+ };
+
+ pinctrl_di2c3_default: di2c3-default-state {
+ function = "I2C3";
+ groups = "DI2C3";
+ };
+ pinctrl_di2c8_default: di2c8-default-state {
+ function = "I2C8";
+ groups = "DI2C8";
+ };
+
+ pinctrl_di2c9_default: di2c9-default-state {
+ function = "I2C9";
+ groups = "DI2C9";
+ };
+
+ pinctrl_di2c10_default: di2c10-default-state {
+ function = "I2C10";
+ groups = "DI2C10";
+ };
+
+ pinctrl_di2c11_default: di2c11-default-state {
+ function = "I2C11";
+ groups = "DI2C11";
+ };
+
+ pinctrl_di2c12_default: di2c12-default-state {
+ function = "I2C12";
+ groups = "DI2C12";
+ };
+
+ pinctrl_di2c13_default: di2c13-default-state {
+ function = "I2C13";
+ groups = "DI2C13";
+ };
+
+ pinctrl_di2c14_default: di2c14-default-state {
+ function = "I2C14";
+ groups = "DI2C14";
+ };
+
+ pinctrl_di2c15_default: di2c15-default-state {
+ function = "I2C15";
+ groups = "DI2C15";
+ };
+
+ pinctrl_ncts0_default: ncts0-default-state {
+ function = "NCTS0";
+ groups = "NCTS0";
+ };
+
+ pinctrl_ndcd0_default: ndcd0-default-state {
+ function = "NDCD0";
+ groups = "NDCD0";
+ };
+
+ pinctrl_ndsr0_default: ndsr0-default-state {
+ function = "NDSR0";
+ groups = "NDSR0";
+ };
+
+ pinctrl_nri0_default: nri0-default-state {
+ function = "NRI0";
+ groups = "NRI0";
+ };
+
+ pinctrl_ndtr0_default: ndtr0-default-state {
+ function = "NDTR0";
+ groups = "NDTR0";
+ };
+
+ pinctrl_nrts0_default: nrts0-default-state {
+ function = "NRTS0";
+ groups = "NRTS0";
+ };
+
+ pinctrl_uart0_default: uart0-default-state {
+ function = "UART0";
+ groups = "UART0";
+ };
+
+ pinctrl_ncts1_default: ncts1-default-state {
+ function = "NCTS1";
+ groups = "NCTS1";
+ };
+
+ pinctrl_ndcd1_default: ndcd1-default-state {
+ function = "NDCD1";
+ groups = "NDCD1";
+ };
+
+ pinctrl_ndsr1_default: ndsr1-default-state {
+ function = "NDSR1";
+ groups = "NDSR1";
+ };
+
+ pinctrl_nri1_default: nri1-default-state {
+ function = "NRI1";
+ groups = "NRI1";
+ };
+
+ pinctrl_ndtr1_default: ndtr1-default-state {
+ function = "NDTR1";
+ groups = "NDTR1";
+ };
+
+ pinctrl_nrts1_default: nrts1-default-state {
+ function = "NRTS1";
+ groups = "NRTS1";
+ };
+
+ pinctrl_uart1_default: uart1-default-state {
+ function = "UART1";
+ groups = "UART1";
+ };
+
+ pinctrl_uart2_default: uart2-default-state {
+ function = "UART2";
+ groups = "UART2";
+ };
+
+ pinctrl_uart3_default: uart3-default-state {
+ function = "UART3";
+ groups = "UART3";
+ };
+
+ pinctrl_ncts5_default: ncts5-default-state {
+ function = "NCTS5";
+ groups = "NCTS5";
+ };
+
+ pinctrl_ndcd5_default: ndcd5-default-state {
+ function = "NDCD5";
+ groups = "NDCD5";
+ };
+
+ pinctrl_ndsr5_default: ndsr5-default-state {
+ function = "NDSR5";
+ groups = "NDSR5";
+ };
+
+ pinctrl_nri5_default: nri5-default-state {
+ function = "NRI5";
+ groups = "NRI5";
+ };
+
+ pinctrl_ndtr5_default: ndtr5-default-state {
+ function = "NDTR5";
+ groups = "NDTR5";
+ };
+
+ pinctrl_nrts5_default: nrts5-default-state {
+ function = "NRTS5";
+ groups = "NRTS5";
+ };
+
+ pinctrl_uart5_default: uart5-default-state {
+ function = "UART5";
+ groups = "UART5";
+ };
+
+ pinctrl_ncts6_default: ncts6-default-state {
+ function = "NCTS6";
+ groups = "NCTS6";
+ };
+
+ pinctrl_ndcd6_default: ndcd6-default-state {
+ function = "NDCD6";
+ groups = "NDCD6";
+ };
+
+ pinctrl_ndsr6_default: ndsr6-default-state {
+ function = "NDSR6";
+ groups = "NDSR6";
+ };
+
+ pinctrl_nri6_default: nri6-default-state {
+ function = "NRI6";
+ groups = "NRI6";
+ };
+
+ pinctrl_ndtr6_default: ndtr6-default-state {
+ function = "NDTR6";
+ groups = "NDTR6";
+ };
+
+ pinctrl_nrts6_default: nrts6-default-state {
+ function = "NRTS6";
+ groups = "NRTS6";
+ };
+
+ pinctrl_uart6_default: uart6-default-state {
+ function = "UART6";
+ groups = "UART6";
+ };
+
+ pinctrl_uart7_default: uart7-default-state {
+ function = "UART7";
+ groups = "UART7";
+ };
+
+ pinctrl_uart8_default: uart8-default-state {
+ function = "UART8";
+ groups = "UART8";
+ };
+
+ pinctrl_uart9_default: uart9-default-state {
+ function = "UART9";
+ groups = "UART9";
+ };
+
+ pinctrl_uart10_default: uart10-default-state {
+ function = "UART10";
+ groups = "UART10";
+ };
+
+ pinctrl_uart11_default: uart11-default-state {
+ function = "UART11";
+ groups = "UART11";
+ };
+
+ pinctrl_pcierc2_perst_default: pcierc2-perst-default-state {
+ function = "PCIERC";
+ groups = "PE2SGRSTN";
+ };
+
+ pinctrl_usb2cud_default: usb2cud-default-state {
+ function = "USB2C";
+ groups = "USB2CUD";
+ };
+
+ pinctrl_usb2cd_default: usb2cd-default-state {
+ function = "USB2C";
+ groups = "USB2CD";
+ };
+
+ pinctrl_usb2ch_default: usb2ch-default-state {
+ function = "USB2C";
+ groups = "USB2CH";
+ };
+
+ pinctrl_usb2cu_default: usb2cu-default-state {
+ function = "USB2C";
+ groups = "USB2CU";
+ };
+
+ pinctrl_usb2dd_default: usb2dd-default-state {
+ function = "USB2D";
+ groups = "USB2DD";
+ };
+
+ pinctrl_usb2dh_default: usb2dh-default-state {
+ function = "USB2D";
+ groups = "USB2DH";
+ };
+
+ pinctrl_wdtrst0n_default: wdtrst0n-default-state {
+ function = "WDTRST0N";
+ groups = "WDTRST0N";
+ };
+
+ pinctrl_wdtrst1n_default: wdtrst1n-default-state {
+ function = "WDTRST1N";
+ groups = "WDTRST1N";
+ };
+
+ pinctrl_wdtrst2n_default: wdtrst2n-default-state {
+ function = "WDTRST2N";
+ groups = "WDTRST2N";
+ };
+
+ pinctrl_wdtrst3n_default: wdtrst3n-default-state {
+ function = "WDTRST3N";
+ groups = "WDTRST3N";
+ };
+
+ pinctrl_wdtrst4n_default: wdtrst4n-default-state {
+ function = "WDTRST4N";
+ groups = "WDTRST4N";
+ };
+
+ pinctrl_wdtrst5n_default: wdtrst5n-default-state {
+ function = "WDTRST5N";
+ groups = "WDTRST5N";
+ };
+
+ pinctrl_wdtrst6n_default: wdtrst6n-default-state {
+ function = "WDTRST6N";
+ groups = "WDTRST6N";
+ };
+
+ pinctrl_wdtrst7n_default: wdtrst7n-default-state {
+ function = "WDTRST7N";
+ groups = "WDTRST7N";
+ };
+};
diff --git a/arch/arm64/boot/dts/aspeed/aspeed-g7-soc1.dtsi b/arch/arm64/boot/dts/aspeed/aspeed-g7-soc1.dtsi
new file mode 100644
index 000000000000..bc990f79e693
--- /dev/null
+++ b/arch/arm64/boot/dts/aspeed/aspeed-g7-soc1.dtsi
@@ -0,0 +1,557 @@
+// SPDX-License-Identifier: GPL-2.0-only OR MIT
+/*
+ * Device Tree Source for AST27xx SoC Family Main Domain peripherals
+ *
+ * Copyright (C) 2026 ASPEED Technology Inc.
+ */
+
+#include <dt-bindings/clock/aspeed,ast2700-scu.h>
+#include <dt-bindings/reset/aspeed,ast2700-scu.h>
+#include <dt-bindings/interrupt-controller/aspeed-scu-ic.h>
+
+&soc1 {
+ fmc: spi@14000000 {
+ reg = <0x0 0x14000000 0x0 0xc4>, <0x1 0x00000000 0x0 0x80000000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "aspeed,ast2700-fmc";
+ status = "disabled";
+ clocks = <&syscon1 SCU1_CLK_AHB>;
+ interrupts-extended = <&intc1 121>;
+ num-cs = <3>;
+
+ flash@0 {
+ reg = < 0 >;
+ compatible = "jedec,spi-nor";
+ spi-max-frequency = <50000000>;
+ spi-rx-bus-width = <2>;
+ status = "disabled";
+ };
+
+ flash@1 {
+ reg = < 1 >;
+ compatible = "jedec,spi-nor";
+ spi-max-frequency = <50000000>;
+ spi-rx-bus-width = <2>;
+ status = "disabled";
+ };
+
+ flash@2 {
+ reg = < 2 >;
+ compatible = "jedec,spi-nor";
+ spi-max-frequency = <50000000>;
+ spi-rx-bus-width = <2>;
+ status = "disabled";
+ };
+ };
+
+ spi0: spi@14010000 {
+ reg = <0x0 0x14010000 0x0 0xc4>, <0x1 0x80000000 0x0 0x80000000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "aspeed,ast2700-spi";
+ clocks = <&syscon1 SCU1_CLK_AHB>;
+ interrupts-extended = <&intc1 122>;
+ status = "disabled";
+ num-cs = <2>;
+
+ flash@0 {
+ reg = < 0 >;
+ compatible = "jedec,spi-nor";
+ spi-max-frequency = <50000000>;
+ spi-rx-bus-width = <2>;
+ status = "disabled";
+ };
+
+ flash@1 {
+ reg = < 1 >;
+ compatible = "jedec,spi-nor";
+ spi-max-frequency = <50000000>;
+ spi-rx-bus-width = <2>;
+ status = "disabled";
+ };
+ };
+
+ spi1: spi@14020000 {
+ reg = <0x0 0x14020000 0x0 0xc4>, <0x2 0x00000000 0x0 0x80000000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "aspeed,ast2700-spi";
+ clocks = <&syscon1 SCU1_CLK_AHB>;
+ interrupts-extended = <&intc1 123>;
+ status = "disabled";
+ num-cs = <2>;
+
+ flash@0 {
+ reg = < 0 >;
+ compatible = "jedec,spi-nor";
+ spi-max-frequency = <50000000>;
+ spi-rx-bus-width = <2>;
+ status = "disabled";
+ };
+
+ flash@1 {
+ reg = < 1 >;
+ compatible = "jedec,spi-nor";
+ spi-max-frequency = <50000000>;
+ spi-rx-bus-width = <2>;
+ status = "disabled";
+ };
+ };
+
+ spi2: spi@14030000 {
+ reg = <0x0 0x14030000 0x0 0x1f0>, <0x2 0x80000000 0x0 0x80000000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "aspeed,ast2700-spi";
+ clocks = <&syscon1 SCU1_CLK_AHB>;
+ resets = <&syscon1 SCU1_RESET_SPI2>;
+ interrupts-extended = <&intc1 124>;
+ num-cs = <2>;
+ status = "disabled";
+ };
+
+ mdio0: mdio@14040000 {
+ compatible = "aspeed,ast2700-mdio", "aspeed,ast2600-mdio";
+ reg = <0 0x14040000 0 0x8>;
+ resets = <&syscon1 SCU1_RESET_MII>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_mdio0_default>;
+ status = "disabled";
+ };
+
+ mdio1: mdio@14040008 {
+ compatible = "aspeed,ast2700-mdio", "aspeed,ast2600-mdio";
+ reg = <0 0x14040008 0 0x8>;
+ resets = <&syscon1 SCU1_RESET_MII>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_mdio1_default>;
+ status = "disabled";
+ };
+
+ mdio2: mdio@14040010 {
+ compatible = "aspeed,ast2700-mdio", "aspeed,ast2600-mdio";
+ reg = <0 0x14040010 0 0x8>;
+ resets = <&syscon1 SCU1_RESET_MII>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_mdio2_default>;
+ status = "disabled";
+ };
+
+ sdio_controller: sdc@14080000 {
+ compatible = "aspeed,ast2700-sd-controller", "aspeed,ast2600-sd-controller";
+ reg = <0 0x14080000 0 0x100>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0x0 0x0 0x14080000 0x10000>;
+ clocks = <&syscon1 SCU1_CLK_GATE_SDCLK>;
+ resets = <&syscon1 SCU1_RESET_SD>;
+ status = "disabled";
+
+ sdhci: sdhci@100 {
+ compatible = "aspeed,ast2700-sdhci", "aspeed,ast2600-sdhci";
+ reg = <0x100 0x100>;
+ sdhci,auto-cmd12;
+ interrupts-extended = <&intc1 161>;
+ clocks = <&syscon1 SCU1_CLK_GATE_SDCLK>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_sd_default>;
+ status = "disabled";
+ };
+ };
+
+ pwm_tach: pwm-tach-controller@140c0000 {
+ compatible = "aspeed,ast2700-pwm-tach", "aspeed,ast2600-pwm-tach";
+ reg = <0x0 0x140c0000 0 0x100>;
+ clocks = <&syscon1 SCU1_CLK_AHB>;
+ resets = <&syscon1 SCU1_RESET_PWM>;
+ #pwm-cells = <3>;
+ status = "disabled";
+ };
+
+ uhci1: usb@14110000 {
+ compatible = "aspeed,ast2700-uhci", "generic-uhci";
+ reg = <0x0 0x14110000 0x0 0x100>;
+ interrupts-extended = <&intc1 155>;
+ #ports = <2>;
+ clocks = <&syscon1 SCU1_CLK_GATE_UHCICLK>;
+ resets = <&syscon1 SCU1_RESET_UHCI>;
+ status = "disabled";
+ };
+
+ vhubc: usb-vhub@14120000 {
+ compatible = "aspeed,ast2700-usb-vhub";
+ reg = <0x0 0x14120000 0x0 0x820>;
+ interrupts-extended = <&intc1 156>;
+ clocks = <&syscon1 SCU1_CLK_GATE_PORTCUSB2CLK>;
+ resets = <&syscon1 SCU1_RESET_PORTC_VHUB_EHCI>;
+ aspeed,vhub-downstream-ports = <7>;
+ aspeed,vhub-generic-endpoints = <21>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usb2cd_default>;
+ status = "disabled";
+ };
+
+ ehci2: usb@14121000 {
+ compatible = "aspeed,ast2700-ehci", "generic-ehci";
+ reg = <0x0 0x14121000 0x0 0x100>;
+ interrupts-extended = <&intc1 156>;
+ clocks = <&syscon1 SCU1_CLK_GATE_PORTCUSB2CLK>;
+ resets = <&syscon1 SCU1_RESET_PORTC_VHUB_EHCI>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usb2ch_default>;
+ status = "disabled";
+ };
+
+ vhubd: usb-vhub@14122000 {
+ compatible = "aspeed,ast2700-usb-vhub";
+ reg = <0x0 0x14122000 0x0 0x820>;
+ interrupts-extended = <&intc1 157>;
+ clocks = <&syscon1 SCU1_CLK_GATE_PORTDUSB2CLK>;
+ resets = <&syscon1 SCU1_RESET_PORTD_VHUB_EHCI>;
+ aspeed,vhub-downstream-ports = <7>;
+ aspeed,vhub-generic-endpoints = <21>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usb2dd_default>;
+ status = "disabled";
+ };
+
+ ehci3: usb@14123000 {
+ compatible = "aspeed,ast2700-ehci", "generic-ehci";
+ reg = <0x0 0x14123000 0x0 0x100>;
+ interrupts-extended = <&intc1 157>;
+ clocks = <&syscon1 SCU1_CLK_GATE_PORTDUSB2CLK>;
+ resets = <&syscon1 SCU1_RESET_PORTD_VHUB_EHCI>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usb2dh_default>;
+ status = "disabled";
+ };
+
+ sram1: sram@14b80000 {
+ compatible = "mmio-sram";
+ reg = <0x0 0x14b80000 0x0 0x40000>;
+ ranges = <0x0 0x0 0x14b80000 0x40000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ soc1-sram@0 {
+ reg = <0x0 0x40000>;
+ export;
+ };
+ };
+
+ adc0: adc@14c00000 {
+ compatible = "aspeed,ast2700-adc0";
+ reg = <0x0 0x14c00000 0 0x100>;
+ clocks = <&syscon1 SCU1_CLK_AHB>;
+ resets = <&syscon1 SCU1_RESET_ADC>;
+ interrupts-extended = <&intc1 80>;
+ #io-channel-cells = <1>;
+ status = "disabled";
+ };
+
+ adc1: adc@14c00100 {
+ compatible = "aspeed,ast2700-adc1";
+ reg = <0x0 0x14c00100 0x0 0x100>;
+ clocks = <&syscon1 SCU1_CLK_AHB>;
+ resets = <&syscon1 SCU1_RESET_ADC>;
+ interrupts-extended = <&intc1 80>;
+ #io-channel-cells = <1>;
+ status = "disabled";
+ };
+
+ syscon1: syscon@14c02000 {
+ compatible = "aspeed,ast2700-scu1", "syscon", "simple-mfd";
+ reg = <0x0 0x14c02000 0x0 0x1000>;
+ ranges = <0x0 0x0 0x14c02000 0x1000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+
+ scu_ic2: interrupt-controller@100 {
+ compatible = "aspeed,ast2700-scu-ic2";
+ reg = <0x100 0x8>;
+ interrupts-extended = <&intc1 160>;
+ #interrupt-cells = <1>;
+ interrupt-controller;
+ };
+
+ scu_ic3: interrupt-controller@108 {
+ compatible = "aspeed,ast2700-scu-ic3";
+ reg = <0x108 0x8>;
+ interrupts-extended = <&intc1 186>;
+ #interrupt-cells = <1>;
+ interrupt-controller;
+ };
+
+ pinctrl1: pinctrl@400 {
+ compatible = "aspeed,ast2700-soc1-pinctrl";
+ reg = <0x400 0x2a0>;
+ };
+ };
+
+ gpio1: gpio@14c0b000 {
+ #gpio-cells = <2>;
+ gpio-controller;
+ compatible = "aspeed,ast2700-gpio";
+ reg = <0x0 0x14c0b000 0x0 0x1000>;
+ interrupts-extended = <&intc1 82>;
+ gpio-ranges = <&pinctrl1 0 0 216>;
+ ngpios = <216>;
+ clocks = <&syscon1 SCU1_CLK_AHB>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ sgpiom0: sgpiom@14c0c000 {
+ #gpio-cells = <2>;
+ gpio-controller;
+ compatible = "aspeed,ast2700-sgpiom";
+ reg = <0x0 0x14c0c000 0x0 0x100>;
+ interrupts-extended = <&intc1 85>;
+ ngpios = <256>;
+ clocks = <&syscon1 SCU1_CLK_APB>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ bus-frequency = <12000000>;
+ status = "disabled";
+ };
+
+ sgpiom1: sgpiom@14c0d000 {
+ #gpio-cells = <2>;
+ gpio-controller;
+ compatible = "aspeed,ast2700-sgpiom";
+ reg = <0x0 0x14c0d000 0x0 0x100>;
+ interrupts-extended = <&intc1 88>;
+ ngpios = <256>;
+ clocks = <&syscon1 SCU1_CLK_APB>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ bus-frequency = <12000000>;
+ status = "disabled";
+ };
+
+ intc1: interrupt-controller@14c18000 {
+ compatible = "aspeed,ast2700-intc1";
+ reg = <0 0x14c18000 0 0x400>;
+ interrupt-controller;
+ interrupt-parent = <&intc0>;
+ #interrupt-cells = <1>;
+ aspeed,interrupt-ranges =
+ <0 6 &intc0 480>, /* M0 ~ M5 */
+ <10 6 &intc0 490>, /* M10 ~ M15 */
+ <20 6 &intc0 500>, /* M20 ~ M25 */
+ <30 6 &intc0 510>, /* M30 ~ M35 */
+ <40 6 &intc0 520>, /* M40 ~ M45 */
+ <50 1 &bootmcu_hlic 11>; /* only 1 pin to BootMCU */
+ };
+
+ uart0: serial@14c33000 {
+ compatible = "ns16550a";
+ reg = <0x0 0x14c33000 0x0 0x100>;
+ reg-shift = <2>;
+ reg-io-width = <4>;
+ clocks = <&syscon1 SCU1_CLK_GATE_UART0CLK>;
+ interrupts-extended = <&intc1 135>;
+ no-loopback-test;
+ status = "disabled";
+ };
+
+ uart1: serial@14c33100 {
+ compatible = "ns16550a";
+ reg = <0x0 0x14c33100 0x0 0x100>;
+ reg-shift = <2>;
+ reg-io-width = <4>;
+ clocks = <&syscon1 SCU1_CLK_GATE_UART1CLK>;
+ interrupts-extended = <&intc1 136>;
+ no-loopback-test;
+ status = "disabled";
+ };
+
+ uart2: serial@14c33200 {
+ compatible = "ns16550a";
+ reg = <0x0 0x14c33200 0x0 0x100>;
+ reg-shift = <2>;
+ reg-io-width = <4>;
+ clocks = <&syscon1 SCU1_CLK_GATE_UART2CLK>;
+ interrupts-extended = <&intc1 137>;
+ no-loopback-test;
+ status = "disabled";
+ };
+
+ uart3: serial@14c33300 {
+ compatible = "ns16550a";
+ reg = <0x0 0x14c33300 0x0 0x100>;
+ reg-shift = <2>;
+ reg-io-width = <4>;
+ clocks = <&syscon1 SCU1_CLK_GATE_UART3CLK>;
+ interrupts-extended = <&intc1 138>;
+ no-loopback-test;
+ status = "disabled";
+ };
+
+ uart5: serial@14c33400 {
+ compatible = "ns16550a";
+ reg = <0x0 0x14c33400 0x0 0x100>;
+ reg-shift = <2>;
+ reg-io-width = <4>;
+ clocks = <&syscon1 SCU1_CLK_GATE_UART5CLK>;
+ interrupts-extended = <&intc1 139>;
+ no-loopback-test;
+ status = "disabled";
+ };
+
+ uart6: serial@14c33500 {
+ compatible = "ns16550a";
+ reg = <0x0 0x14c33500 0x0 0x100>;
+ reg-shift = <2>;
+ reg-io-width = <4>;
+ clocks = <&syscon1 SCU1_CLK_GATE_UART6CLK>;
+ interrupts-extended = <&intc1 140>;
+ no-loopback-test;
+ status = "disabled";
+ };
+
+ uart7: serial@14c33600 {
+ compatible = "ns16550a";
+ reg = <0x0 0x14c33600 0x0 0x100>;
+ reg-shift = <2>;
+ reg-io-width = <4>;
+ clocks = <&syscon1 SCU1_CLK_GATE_UART7CLK>;
+ interrupts-extended = <&intc1 141>;
+ no-loopback-test;
+ status = "disabled";
+ };
+
+ uart8: serial@14c33700 {
+ compatible = "ns16550a";
+ reg = <0x0 0x14c33700 0x0 0x100>;
+ reg-shift = <2>;
+ reg-io-width = <4>;
+ clocks = <&syscon1 SCU1_CLK_GATE_UART8CLK>;
+ interrupts-extended = <&intc1 142>;
+ no-loopback-test;
+ status = "disabled";
+ };
+
+ uart9: serial@14c33800 {
+ compatible = "ns16550a";
+ reg = <0x0 0x14c33800 0x0 0x100>;
+ reg-shift = <2>;
+ reg-io-width = <4>;
+ clocks = <&syscon1 SCU1_CLK_GATE_UART9CLK>;
+ interrupts-extended = <&intc1 143>;
+ no-loopback-test;
+ status = "disabled";
+ };
+
+ uart10: serial@14c33900 {
+ compatible = "ns16550a";
+ reg = <0x0 0x14c33900 0x0 0x100>;
+ reg-shift = <2>;
+ reg-io-width = <4>;
+ clocks = <&syscon1 SCU1_CLK_GATE_UART10CLK>;
+ interrupts-extended = <&intc1 144>;
+ no-loopback-test;
+ status = "disabled";
+ };
+
+ uart11: serial@14c33a00 {
+ compatible = "ns16550a";
+ reg = <0x0 0x14c33a00 0x0 0x100>;
+ reg-shift = <2>;
+ reg-io-width = <4>;
+ clocks = <&syscon1 SCU1_CLK_GATE_UART11CLK>;
+ interrupts-extended = <&intc1 145>;
+ no-loopback-test;
+ status = "disabled";
+ };
+
+ uart12: serial@14c33b00 {
+ compatible = "ns16550a";
+ reg = <0x0 0x14c33b00 0x0 0x100>;
+ reg-shift = <2>;
+ reg-io-width = <4>;
+ clocks = <&syscon1 SCU1_CLK_GATE_UART12CLK>;
+ interrupts-extended = <&intc1 146>;
+ no-loopback-test;
+ status = "disabled";
+ };
+
+ uart13: serial@14c33c00 {
+ compatible = "ns16550a";
+ reg = <0x0 0x14c33c00 0x0 0x100>;
+ reg-shift = <2>;
+ reg-io-width = <4>;
+ clocks = <&syscon1 SCU1_CLK_UART13>;
+ interrupts-extended = <&intc1 23>;
+ no-loopback-test;
+ status = "disabled";
+ };
+
+ uart14: serial@14c33d00 {
+ compatible = "ns16550a";
+ reg = <0x0 0x14c33d00 0x0 0x100>;
+ reg-shift = <2>;
+ reg-io-width = <4>;
+ clocks = <&syscon1 SCU1_CLK_UART14>;
+ interrupts-extended = <&intc1 55>;
+ no-loopback-test;
+ status = "disabled";
+ };
+
+ wdt0: watchdog@14c37000 {
+ compatible = "aspeed,ast2700-wdt";
+ reg = <0x0 0x14c37000 0x0 0x80>;
+ };
+
+ wdt1: watchdog@14c37080 {
+ compatible = "aspeed,ast2700-wdt";
+ reg = <0x0 0x14c37080 0x0 0x80>;
+ };
+
+ wdt2: watchdog@14c37100 {
+ compatible = "aspeed,ast2700-wdt";
+ reg = <0x0 0x14c37100 0x0 0x80>;
+ status = "disabled";
+ };
+
+ wdt3: watchdog@14c37180 {
+ compatible = "aspeed,ast2700-wdt";
+ reg = <0x0 0x14c37180 0x0 0x80>;
+ status = "disabled";
+ };
+
+ mbox2: mbox@14c39200 {
+ compatible = "aspeed,ast2700-mailbox";
+ reg = <0x0 0x14c39200 0x0 0x100>, <0x0 0x14c39300 0x0 0x100>;
+ reg-names = "tx", "rx";
+ interrupts-extended = <&intc1 177>;
+ #mbox-cells = <1>;
+ };
+
+ fsim0: fsi@21800000 {
+ compatible = "aspeed,ast2700-fsi-master";
+ reg = <0x0 0x21800000 0x0 0x94>;
+ interrupts-extended = <&intc1 166>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_fsi0_default>;
+ clocks = <&syscon1 SCU1_CLK_GATE_FSICLK>;
+ resets = <&syscon1 SCU1_RESET_FSI>;
+ status = "disabled";
+ };
+
+ fsim1: fsi@23800000 {
+ compatible = "aspeed,ast2700-fsi-master";
+ reg = <0x0 0x23800000 0x0 0x94>;
+ interrupts-extended = <&intc1 167>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_fsi2_default>;
+ clocks = <&syscon1 SCU1_CLK_GATE_FSICLK>;
+ resets = <&syscon1 SCU1_RESET_FSI>;
+ status = "disabled";
+ };
+};
+
+#include "aspeed-g7-soc1-pinctrl.dtsi"
diff --git a/arch/arm64/boot/dts/aspeed/ast2700-evb.dts b/arch/arm64/boot/dts/aspeed/ast2700-evb.dts
new file mode 100644
index 000000000000..fe8f0b80fb2c
--- /dev/null
+++ b/arch/arm64/boot/dts/aspeed/ast2700-evb.dts
@@ -0,0 +1,65 @@
+// SPDX-License-Identifier: GPL-2.0-only OR MIT
+/*
+ * Device Tree Source AST2700 EVB
+ *
+ * Copyright (C) 2026 ASPEED Technology Inc.
+ */
+
+/dts-v1/;
+#include "aspeed-g7-a35.dtsi"
+
+/ {
+ model = "AST2700 EVB";
+ compatible = "aspeed,ast2700-evb", "aspeed,ast2700";
+
+ aliases {
+ serial0 = &uart12; /* console port */
+ };
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+
+ memory@400000000 {
+ device_type = "memory";
+ reg = <0x4 0x00000000 0x0 0x40000000>;
+ };
+};
+
+&fmc {
+ status = "okay";
+ pinctrl-0 = <&pinctrl_fwspi_quad_default>;
+ pinctrl-names = "default";
+
+ flash@0 {
+ status = "okay";
+ m25p,fast-read;
+ label = "bmc";
+ spi-max-frequency = <50000000>;
+ spi-tx-bus-width = <4>;
+ spi-rx-bus-width = <4>;
+#include "aspeed-evb-flash-layout-128.dtsi"
+ };
+
+ flash@1 {
+ status = "okay";
+ m25p,fast-read;
+ label = "fmc0:1";
+ spi-max-frequency = <50000000>;
+ spi-tx-bus-width = <4>;
+ spi-rx-bus-width = <4>;
+ };
+
+ flash@2 {
+ status = "disabled";
+ m25p,fast-read;
+ label = "fmc0:2";
+ spi-max-frequency = <50000000>;
+ spi-tx-bus-width = <4>;
+ spi-rx-bus-width = <4>;
+ };
+};
+
+&uart12 {
+ status = "okay";
+};
--
2.34.1
^ permalink raw reply related
* [PATCH v9 2/4] arm64: Kconfig: Add ASPEED SoC family Kconfig support
From: Ryan Chen @ 2026-06-09 2:47 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Joel Stanley,
Andrew Jeffery, Catalin Marinas, Will Deacon, Arnd Bergmann,
Krzysztof Kozlowski, Alexandre Belloni, Linus Walleij,
Drew Fustini, Paul Walmsley, Palmer Dabbelt, Albert Ou,
Alexandre Ghiti
Cc: devicetree, linux-arm-kernel, linux-aspeed, linux-kernel, soc,
linux-riscv, Ryan Chen
In-Reply-To: <20260609-upstream_ast2700-v9-0-f631752f0cb1@aspeedtech.com>
Add support for ASPEED SoC family like ast27XX 8th
generation ASPEED BMCs.
Signed-off-by: Ryan Chen <ryan_chen@aspeedtech.com>
---
arch/arm64/Kconfig.platforms | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms
index dc995a732117..d2acfac73003 100644
--- a/arch/arm64/Kconfig.platforms
+++ b/arch/arm64/Kconfig.platforms
@@ -48,6 +48,12 @@ config ARCH_ARTPEC
help
This enables support for the ARMv8 based ARTPEC SoC Family.
+config ARCH_ASPEED
+ bool "Aspeed SoC family"
+ help
+ This enables support for ASPEED's SoC family, such as the
+ ast27XX 8th generation Baseboard Management Controller (BMC).
+
config ARCH_AXIADO
bool "Axiado SoC Family"
select GPIOLIB
--
2.34.1
^ permalink raw reply related
* [PATCH v9 1/4] dt-bindings: arm: aspeed: Add AST2700 board compatible
From: Ryan Chen @ 2026-06-09 2:47 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Joel Stanley,
Andrew Jeffery, Catalin Marinas, Will Deacon, Arnd Bergmann,
Krzysztof Kozlowski, Alexandre Belloni, Linus Walleij,
Drew Fustini, Paul Walmsley, Palmer Dabbelt, Albert Ou,
Alexandre Ghiti
Cc: devicetree, linux-arm-kernel, linux-aspeed, linux-kernel, soc,
linux-riscv, Ryan Chen, Conor Dooley
In-Reply-To: <20260609-upstream_ast2700-v9-0-f631752f0cb1@aspeedtech.com>
Add device tree compatible string for AST2700 based boards
("aspeed,ast2700-evb" and "aspeed,ast2700") to the Aspeed SoC
board bindings. This allows proper schema validation and
enables support for AST2700 platforms.
Signed-off-by: Ryan Chen <ryan_chen@aspeedtech.com>
Acked-by: Conor Dooley <conor.dooley@microchip.com>
---
Documentation/devicetree/bindings/arm/aspeed/aspeed.yaml | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/Documentation/devicetree/bindings/arm/aspeed/aspeed.yaml b/Documentation/devicetree/bindings/arm/aspeed/aspeed.yaml
index 9ba195b8f22d..dd7996960de3 100644
--- a/Documentation/devicetree/bindings/arm/aspeed/aspeed.yaml
+++ b/Documentation/devicetree/bindings/arm/aspeed/aspeed.yaml
@@ -119,4 +119,10 @@ properties:
- ufispace,ncplite-bmc
- const: aspeed,ast2600
+ - description: AST2700 based boards
+ items:
+ - enum:
+ - aspeed,ast2700-evb
+ - const: aspeed,ast2700
+
additionalProperties: true
--
2.34.1
^ permalink raw reply related
* [PATCH v9 0/4] Introduce ASPEED AST27xx BMC SoC
From: Ryan Chen @ 2026-06-09 2:47 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Joel Stanley,
Andrew Jeffery, Catalin Marinas, Will Deacon, Arnd Bergmann,
Krzysztof Kozlowski, Alexandre Belloni, Linus Walleij,
Drew Fustini, Paul Walmsley, Palmer Dabbelt, Albert Ou,
Alexandre Ghiti
Cc: devicetree, linux-arm-kernel, linux-aspeed, linux-kernel, soc,
linux-riscv, Ryan Chen, Conor Dooley, Krzysztof Kozlowski
This introduces initial support for the Aspeed AST27xx SoC and the AST2700
Evaluation Board (EVB) to the Linux kernel. The AST27xx is the 8th
generation Baseboard Management Controller (BMC) SoC from Aspeed,
featuring improved performance, enhanced security, and expanded I/O
capabilities compared to previous generations.
AST27xx SOC Family
- https://www.aspeedtech.com/server_ast2700/
- https://www.aspeedtech.com/server_ast2720/
- https://www.aspeedtech.com/server_ast2750/
Bindings Dependencies:
check with "make CHECK_DTBS=y W=1 arch/arm64/boot/dts/aspeed/ dtbs"
- scu/scu-ic/silicon-id: Documentation/devicetree/bindings/mfd/aspeed,ast2x00-scu.yaml
- intc: Documentation/devicetree/bindings/interrupt-controller/aspeed,ast2700-interrupt.yaml
- scu-ic: Documentation/devicetree/bindings/interrupt-controller/aspeed,ast2500-scu-ic.yaml
- pinctrl soc0: Documentation/devicetree/bindings/pinctrl/aspeed,ast2700-soc0-pinctrl.yaml
- pinctrl soc1: Documentation/devicetree/bindings/pinctrl/aspeed,ast2700-soc1-pinctrl.yaml
- gpio: Documentation/devicetree/bindings/gpio/aspeed,ast2400-gpio.yaml
- sgpio: Documentation/devicetree/bindings/gpio/aspeed,sgpio.yaml
- fmc/spi: Documentation/devicetree/bindings/spi/aspeed,ast2600-fmc.yaml
- mdio: Documentation/devicetree/bindings/net/aspeed,ast2600-mdio.yaml
- sd/sdhci: Documentation/devicetree/bindings/mmc/aspeed,sdhci.yaml
- usb-vhub: Documentation/devicetree/bindings/usb/aspeed,usb-vhub.yaml
- ehci: Documentation/devicetree/bindings/usb/generic-ehci.yaml
- uhci: Documentation/devicetree/bindings/usb/usb-uhci.yaml
- wdt: Documentation/devicetree/bindings/watchdog/aspeed,ast2400-wdt.yaml
- mailbox: Documentation/devicetree/bindings/mailbox/aspeed,ast2700-mailbox.yaml
- adc: Documentation/devicetree/bindings/iio/adc/aspeed,ast2600-adc.yaml
- pwm-tach: Documentation/devicetree/bindings/hwmon/aspeed,g6-pwm-tach.yaml
- fsi: Documentation/devicetree/bindings/fsi/aspeed,ast2600-fsi-master.yaml
Signed-off-by: Ryan Chen <ryan_chen@aspeedtech.com>
---
Changes in v9:
- use b4 send
- rebase on linux-next
- split aspeed-g7-common.dtsi to aspeed-g7-soc0/1.dtsi
- update all interrupt-extend by use aspeed,ast2700-intc0/1 parent
- MAINTAINERS: add arch/arm64/boot/dts/aspeed/ entry
- Kconfig.platforms: reword ARCH_ASPEED help text
- cover: complete bindings dependencies list and fix intc binding path
- Link to v8: https://lore.kernel.org/all/20251112101157.2149169-1-ryan_chen@aspeedtech.com/
Changes in v8:
- Kconfig.platforms
- update commit message and help description.
- aspeed-g7-a35.dtsi,aspeed-g7-common.dtsi,ast2700-evb.dts
- change license using a dual license of MIT + GPL2.0+
- add company copyright.
- merge original v7 patch(3/5) and (4/5) to 1 v8patch(3/4)
- that can do build test with make CHECK_DTBS=y W=1 arch/arm64/boot/dts/aspeed/ dtbs
- Link to v7: https://lore.kernel.org/all/20251107055629.4075519-1-ryan_chen@aspeedtech.com/
Changes in v7:
- remove aspeed,ast2x00-scu.yaml modify
- separate aspeed-g7.dtsi to aspeed-g7-a35.dtsi and aspeed-g7-common.dtsi
-move aliases to ast2700-evb.dts file
-Link to v6: https://lore.kernel.org/all/20251022070543.1169173-1-ryan_chen@aspeedtech.com/
Changes in v6:
- rebased on v6.18-rc1
- aspeed,ast2x00-scu.yaml
- fixed dt-binding yaml issuse report.
-Linke to v5: https://lore.kernel.org/all/20250901031311.1247805-1-ryan_chen@aspeedtech.com/
Changes in v5:
- modify ast27XX 7th generation description to 8th generation.
- aspeed.yaml
- modify missing blank line.
- Kconfig.platforms
- modify ast27XX 7th generation to 8th generation.
-Link to v4: https://lore.kernel.org/all/20250821080214.513090-1-ryan_chen@aspeedtech.com/
Changes in v4:
- make CHECK_DTBS=y arch/arm64/boot/dts/aspeed/ fix.
- modify commit message remove itemlize.
- remove modify aspeed,ast2700-intc.yaml patch.
- aspeed.yaml
- Add AST2700 board compatible.
- aspeed-g7.dtsi
- modify all size-cells from 1 to 2.
- add serial aliases, gpio, mdio, uart0 ~ 14.
- add firmware for optee, reserved memory for atf and optee.
- modify cpu@0 to cpu0: cpu@0.
- fix intc-ic for yaml dependency.
- ast2700-evb.dts
- update stdout-path = "serial12:115200n8";
-Link to v3: https://lore.kernel.org/all/20241212155237.848336-1-kevin_chen@aspeedtech.com/
Changes in v3:
- Split clk and reset driver to other commits, which are in series of
"Add support for AST2700 clk driver".
- For BMC console by UART12, add uart12 using ASPEED INTC architecture.
aspeed,ast2700-intc.yaml
- Add minItems to 1 to fix the warning by "make dtbs_check W=1".
- Add intc1 into example.
Kconfig.platforms
- Remove MACH_ASPEED_G7.
-Link to v2: https://lore.kernel.org/all/20240802090544.2741206-1-kevin_chen@aspeedtech.com/
Changes in v2:
-Link to v1: https://lore.kernel.org/all/20250612100933.3007673-1-ryan_chen@aspeedtech.com/
---
Ryan Chen (4):
dt-bindings: arm: aspeed: Add AST2700 board compatible
arm64: Kconfig: Add ASPEED SoC family Kconfig support
arm64: dts: aspeed: Add initial AST27xx SoC device tree
arm64: configs: Update defconfig for AST2700 platform support
.../devicetree/bindings/arm/aspeed/aspeed.yaml | 6 +
MAINTAINERS | 1 +
arch/arm64/Kconfig.platforms | 6 +
arch/arm64/boot/dts/Makefile | 1 +
arch/arm64/boot/dts/aspeed/Makefile | 4 +
.../dts/aspeed/aspeed-evb-flash-layout-128.dtsi | 32 +
arch/arm64/boot/dts/aspeed/aspeed-g7-a35.dtsi | 196 ++++
.../boot/dts/aspeed/aspeed-g7-soc0-pinctrl.dtsi | 225 ++++
arch/arm64/boot/dts/aspeed/aspeed-g7-soc0.dtsi | 230 ++++
.../boot/dts/aspeed/aspeed-g7-soc1-pinctrl.dtsi | 1113 ++++++++++++++++++++
arch/arm64/boot/dts/aspeed/aspeed-g7-soc1.dtsi | 557 ++++++++++
arch/arm64/boot/dts/aspeed/ast2700-evb.dts | 65 ++
arch/arm64/configs/defconfig | 1 +
13 files changed, 2437 insertions(+)
---
base-commit: 6e845bcb78c95af935094040bd4edc3c2b6dd784
change-id: 20260205-upstream_ast2700-6efec42ab228
Best regards,
--
Ryan Chen <ryan_chen@aspeedtech.com>
^ permalink raw reply
* Re: [PATCH v3] net: stmmac: fix fatal bus error on resume by reinitializing RX buffers
From: Jakub Kicinski @ 2026-06-09 2:30 UTC (permalink / raw)
To: Ding Hui
Cc: Andrew Lunn, David S. Miller, Eric Dumazet, Paolo Abeni,
Maxime Coquelin, Alexandre Torgue, Russell King (Oracle),
Maxime Chevallier, Ding Hui, open list:STMMAC ETHERNET DRIVER,
moderated list:ARM/STM32 ARCHITECTURE,
moderated list:ARM/STM32 ARCHITECTURE, open list, j.raczynski,
xiasanbo, yangchen11, liuxuanjun
In-Reply-To: <20260604144557.3175399-1-dinghui1111@163.com>
On Thu, 4 Jun 2026 22:45:54 +0800 Ding Hui wrote:
> +/**
> + * stmmac_reinit_rx_descriptors - re-program RX descriptor buffer addresses
> + * after stmmac_clear_descriptors()
> + * @priv: driver private structure
> + * @dma_conf: structure holding the dma data
> + * @queue: RX queue index
nit:
kernel-doc script says:
Warning: drivers/net/ethernet/stmicro/stmmac/stmmac_main.c:1733 No description found for return value of 'stmmac_reinit_rx_descriptors'
You need a Returns: statement in this kdoc
--
pw-bot: cr
^ permalink raw reply
* Re: [PATCH net-next] net: airoha: Add TCP LRO support
From: Jakub Kicinski @ 2026-06-09 2:15 UTC (permalink / raw)
To: Lorenzo Bianconi
Cc: Andrew Lunn, David S. Miller, Eric Dumazet, Paolo Abeni,
Alexander Lobakin, linux-arm-kernel, linux-mediatek, netdev,
Madhur Agrawal
In-Reply-To: <20260606-airoha-eth-lro-v1-1-0ebceb0eafc3@kernel.org>
On Sat, 06 Jun 2026 16:45:28 +0200 Lorenzo Bianconi wrote:
> Add hardware TCP Large Receive Offload (LRO) support to the airoha_eth
> driver, leveraging the EN7581/AN7583 SoC's 8 dedicated LRO hardware queues
> mapped to RX queues 24–31. LRO hw offloading does not support
> Scatter-Gather (SG) so it is required to increase the page_pool allocation
> order to 2 for RX queues 24–31 (LRO queues).
NIPA says this doesn't apply
--
pw-bot: cr
^ permalink raw reply
* Re: [PATCH] arm_mpam: Fix MPAMCFG_MBW_PBM register setting
From: Fenghua Yu @ 2026-06-09 2:06 UTC (permalink / raw)
To: Gavin Shan, Ben Horgan, James Morse, Reinette Chatre,
Catalin Marinas, Shaopeng Tan, Jesse Chick
Cc: linux-kernel, linux-arm-kernel, Matt Ochs
In-Reply-To: <1a9e10ef-266e-43c7-8722-eb61a1af1565@redhat.com>
Hi, Gavin,
On 6/7/26 21:46, Gavin Shan wrote:
> Hi Fenghua,
>
> On 6/7/26 3:09 PM, Fenghua Yu wrote:
>> MPAMCFG_MBW_PBM is written from cfg if cfg has the MBW partition feature.
>> It is reset when cfg does not have the MBW partition feature.
>>
>> But the register handling is reversed. This may cause an incorrect
>> register setting. For example, during an MPAM reset, reset_cfg is
>> empty (no MBW partition feature set), and cfg->mbw_pbm is 0. Instead of
>> resetting MPAMCFG_MBW_PBM to all 1's, the current logic will set it to
>> cfg->mbw_pbm, which is 0.
>>
>> Fix the issue by swapping the if/else branches.
>>
>> Fixes: a1cb6577f575 ("arm_mpam: Reset when feature configuration bit
>> unset")
>> Reported-by: Matt Ochs <mochs@nvidia.com>
>> Signed-off-by: Fenghua Yu <fenghuay@nvidia.com>
>> ---
>> drivers/resctrl/mpam_devices.c | 4 ++--
>> 1 file changed, 2 insertions(+), 2 deletions(-)
>>
>
> The fix itself looks reasonable to me, but two questions below.
>
> Reviewed-by: Gavin Shan <gshan@redhat.com>
Thank you for reviewing the patch!
>
>> diff --git a/drivers/resctrl/mpam_devices.c b/drivers/resctrl/
>> mpam_devices.c
>> index 4b93e89c2678..d8b0383cee92 100644
>> --- a/drivers/resctrl/mpam_devices.c
>> +++ b/drivers/resctrl/mpam_devices.c
>> @@ -1570,9 +1570,9 @@ static void mpam_reprogram_ris_partid(struct
>> mpam_msc_ris *ris, u16 partid,
>> if (mpam_has_feature(mpam_feat_mbw_part, rprops)) {
>> if (mpam_has_feature(mpam_feat_mbw_part, cfg))
>> - mpam_reset_msc_bitmap(msc, MPAMCFG_MBW_PBM, rprops-
>> >mbw_pbm_bits);
>> - else
>> mpam_write_partsel_reg(msc, MBW_PBM, cfg->mbw_pbm);
>> + else
>> + mpam_reset_msc_bitmap(msc, MPAMCFG_MBW_PBM, rprops-
>> >mbw_pbm_bits);
>> }
>> if (mpam_has_feature(mpam_feat_mbw_min, rprops)) {
>
> Which machine or system where mpam_feat_mbw_part is set on RIS? As I can
> remember, this feature isn't available on grace-hopper.
Neither Grace nor Vera supports this feature.
>
> Besides, I don't think this feature is well handled at present because
> mpam_config::mbw_pbm is only 32-bits in length, which doesn't match with
> the maximal length of the bit map (4096) as documented in the spec.
Right. The current code only can support up to 32 bits of PBM bitmap. If
PBM bitmp length is bigger than 32 bits, it's broken. I guess we will
need to handle this feature properly when hardware supports more than 32
bits of PBM bitmap.
Ditto for CPBM bitmap.
This patch currently only fixes the regression issue introduced in
commit a1cb6577f575 regardless size of PBM bitmap.
Thanks.
-Fenghua
^ permalink raw reply
* Re: [PATCH] ARM: arch/arm/kernel/signal.c: resolve set-but-not-used warning
From: Ethan Nelson-Moore @ 2026-06-09 2:02 UTC (permalink / raw)
To: Baruch Siach
Cc: linux-arm-kernel, linux-kernel, Russell King, Arnd Bergmann,
Thomas Weißschuh
In-Reply-To: <87tsrd8ug1.fsf@tarshish>
Hi, Baruch,
On Sun, Jun 7, 2026 at 10:36 PM Baruch Siach <baruch@tkos.co.il> wrote:
> __maybe_unused is a common attribute marking local variables that are not
> always used. I find it nicer than another layer of #ifdef.
That's a good point. The compiler will just optimize it out in this
case. I'll send a new version of the patch using this attribute.
Ethan
^ permalink raw reply
* [PATCH] firmware: imx: sm-misc: Add NULL check for kmalloc in syslog_show
From: Li Jun @ 2026-06-09 0:45 UTC (permalink / raw)
To: lijun01, Frank.Li, s.hauer, imx, linux-kernel, kernel, festevam,
peng.fan, shawnguo, krzysztof.kozlowski, linux-arm-kernel
Add a proper NULL check for the kmalloc() return value in syslog_show().
If memory allocation fails, syslog would be NULL and passing it to
misc_syslog() could lead to a NULL pointer dereference.
Signed-off-by: Li Jun <lijun01@kylinos.cn>
---
drivers/firmware/imx/sm-misc.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/drivers/firmware/imx/sm-misc.c b/drivers/firmware/imx/sm-misc.c
index ac9af824c2d4..fb8d7bdb5b08 100644
--- a/drivers/firmware/imx/sm-misc.c
+++ b/drivers/firmware/imx/sm-misc.c
@@ -79,6 +79,9 @@ static int syslog_show(struct seq_file *file, void *priv)
u16 size = SZ_4K / 4;
int ret;
+ if (!syslog)
+ return -ENOMEM;
+
if (!ph)
return -ENODEV;
--
2.25.1
^ permalink raw reply related
* RE: [PATCH v4] perf/arm_pmu: Skip PMCCNTR_EL0 on NVIDIA Olympus
From: Besar Wicaksono @ 2026-06-09 0:01 UTC (permalink / raw)
To: Will Deacon
Cc: mark.rutland@arm.com, james.clark@linaro.org,
yangyccccc@gmail.com, linux-arm-kernel@lists.infradead.org,
linux-kernel@vger.kernel.org, linux-tegra@vger.kernel.org,
Thierry Reding, Jon Hunter, Vikram Sethi, Rich Wiley,
Shanker Donthineni, Matt Ochs, Nirmoy Das, Sean Kelley
In-Reply-To: <agxMXsznrU3mvcfE@willie-the-truck>
Hi Will,
My apology for taking a while to respond.
Please see my reply inline.
> -----Original Message-----
> From: Will Deacon <will@kernel.org>
> Sent: Tuesday, May 19, 2026 6:41 AM
> To: Besar Wicaksono <bwicaksono@nvidia.com>
> Cc: mark.rutland@arm.com; james.clark@linaro.org; yangyccccc@gmail.com;
> linux-arm-kernel@lists.infradead.org; linux-kernel@vger.kernel.org; linux-
> tegra@vger.kernel.org; Thierry Reding <treding@nvidia.com>; Jon Hunter
> <jonathanh@nvidia.com>; Vikram Sethi <vsethi@nvidia.com>; Rich Wiley
> <rwiley@nvidia.com>; Shanker Donthineni <sdonthineni@nvidia.com>; Matt
> Ochs <mochs@nvidia.com>; Nirmoy Das <nirmoyd@nvidia.com>; Sean Kelley
> <skelley@nvidia.com>
> Subject: Re: [PATCH v4] perf/arm_pmu: Skip PMCCNTR_EL0 on NVIDIA
> Olympus
>
> External email: Use caution opening links or attachments
>
>
> On Mon, May 04, 2026 at 05:52:04PM +0000, Besar Wicaksono wrote:
> > PMCCNTR_EL0 may continue to increment on NVIDIA Olympus CPUs while
> the
> > PE is in WFI/WFE. That does not necessarily match the CPU_CYCLES event
> > counted by a programmable counter, so using PMCCNTR_EL0 for cycles can
> > give results that differ from the programmable counter path.
> >
> > Extend the existing PMCCNTR avoidance decision from the SMT case to
> > also cover Olympus. Store the result in the common arm_pmu state at
> > registration time, so arm_pmuv3 can keep using a single flag when
> > deciding whether CPU_CYCLES may use PMCCNTR_EL0.
> >
> > Signed-off-by: Besar Wicaksono <bwicaksono@nvidia.com>
> > ---
> >
> > Changes from v1:
> > * add CONFIG_ARM64 check to fix build error found by kernel test robot
> > * add explicit include of <asm/cputype.h>
> > v1: https://lore.kernel.org/linux-arm-kernel/20260406232034.2566133-1-
> bwicaksono@nvidia.com/
> >
> > Changes from v2:
> > * Move the Olympus PMCCNTR avoidance check from arm_pmuv3.c to the
> > common arm_pmu registration path.
> > * Replace the PMUv3-only has_smt flag with avoid_pmccntr, covering both
> > the existing SMT restriction and the Olympus MIDR restriction.
> > * Use the cached per-CPU MIDR from cpu_data instead of calling
> > is_midr_in_range_list() from armv8pmu_can_use_pmccntr().
> > * Add the required asm/cpu.h include for cpu_data.
> > v2: https://lore.kernel.org/linux-arm-kernel/20260421203856.3539186-1-
> bwicaksono@nvidia.com/#t
> >
> > Changes from v3:
> > * Move avoidance check based on MIDR to __armv8pmu_probe_pmu() to
> make sure
> > the MIDR is retrieved from the correct online CPU.
> > v3: https://lore.kernel.org/linux-arm-kernel/20260429215614.1793131-1-
> bwicaksono@nvidia.com/
> >
> > ---
> > drivers/perf/arm_pmu.c | 7 ++++-
> > drivers/perf/arm_pmuv3.c | 51
> +++++++++++++++++++++++++++++++-----
> > include/linux/perf/arm_pmu.h | 2 +-
> > 3 files changed, 51 insertions(+), 9 deletions(-)
> >
> > diff --git a/drivers/perf/arm_pmu.c b/drivers/perf/arm_pmu.c
> > index 939bcbd433aa..aa1dac0b440f 100644
> > --- a/drivers/perf/arm_pmu.c
> > +++ b/drivers/perf/arm_pmu.c
> > @@ -931,8 +931,13 @@ int armpmu_register(struct arm_pmu *pmu)
> > /*
> > * By this stage we know our supported CPUs on either DT/ACPI
> platforms,
> > * detect the SMT implementation.
> > + * On SMT CPUs, the PMCCNTR_EL0 increments from the processor clock
> rather
> > + * than the PE clock (ARM DDI0487 L.b D13.1.3) which means it'll
> continue
> > + * counting on a WFI PE if one of its SMT sibling is not idle on a
> > + * multi-threaded implementation. So don't use it on SMT cores.
> > */
> > - pmu->has_smt = topology_core_has_smt(cpumask_first(&pmu-
> >supported_cpus));
> > + pmu->avoid_pmccntr |=
> > + topology_core_has_smt(cpumask_first(&pmu->supported_cpus));
> >
> > if (!pmu->set_event_filter)
> > pmu->pmu.capabilities |= PERF_PMU_CAP_NO_EXCLUDE;
> > diff --git a/drivers/perf/arm_pmuv3.c b/drivers/perf/arm_pmuv3.c
> > index 8014ff766cff..1ee4a09d0dcc 100644
> > --- a/drivers/perf/arm_pmuv3.c
> > +++ b/drivers/perf/arm_pmuv3.c
> > @@ -8,6 +8,7 @@
> > * This code is based heavily on the ARMv7 perf event code.
> > */
> >
> > +#include <asm/cputype.h>
> > #include <asm/irq_regs.h>
> > #include <asm/perf_event.h>
> > #include <asm/virt.h>
> > @@ -1002,13 +1003,7 @@ static bool armv8pmu_can_use_pmccntr(struct
> pmu_hw_events *cpuc,
> > if (has_branch_stack(event))
> > return false;
> >
> > - /*
> > - * The PMCCNTR_EL0 increments from the processor clock rather than
> > - * the PE clock (ARM DDI0487 L.b D13.1.3) which means it'll continue
> > - * counting on a WFI PE if one of its SMT sibling is not idle on a
> > - * multi-threaded implementation. So don't use it on SMT cores.
> > - */
> > - if (cpu_pmu->has_smt)
> > + if (cpu_pmu->avoid_pmccntr)
> > return false;
> >
> > return true;
> > @@ -1299,6 +1294,41 @@ static int armv8_vulcan_map_event(struct
> perf_event *event)
> > &armv8_vulcan_perf_cache_map);
> > }
> >
> > +#ifdef CONFIG_ARM64
> > +/*
> > + * List of CPUs that should avoid using PMCCNTR_EL0.
> > + */
> > +static struct midr_range armv8pmu_avoid_pmccntr_cpus[] = {
> > + /*
> > + * The PMCCNTR_EL0 in Olympus CPU may still increment while in
> WFI/WFE state.
> > + * This is an implementation specific behavior and not an erratum.
> > + *
> > + * From ARM DDI0487 D14.4:
> > + * It is IMPLEMENTATION SPECIFIC whether CPU_CYCLES and PMCCNTR
> count
> > + * when the PE is in WFI or WFE state, even if the clocks are not stopped.
>
> So surely the weird part here is that Olypmus chose one behaviour for
> PMCCNTR and another for the CPU_CYCLES event? The Arm ARM text isn't
That is correct.
> clear to me as to whether that's permitted but I think we should call
> it out here.
>
Sure, I will call it out explicitly.
> > + * From ARM DDI0487 D24.5.2:
> > + * All counters are subject to any changes in clock frequency, including
> > + * clock stopping caused by the WFI and WFE instructions.
> > + * This means that it is CONSTRAINED UNPREDICTABLE whether or not
> > + * PMCCNTR_EL0 continues to increment when clocks are stopped by
> WFI and
> > + * WFE instructions.
> > + */
> > + MIDR_ALL_VERSIONS(MIDR_NVIDIA_OLYMPUS),
> > + {}
> > +};
> > +
> > +static bool armv8pmu_is_in_avoid_pmccntr_cpus(void)
> > +{
> > + return is_midr_in_range_list(armv8pmu_avoid_pmccntr_cpus);
> > +}
> > +#else
> > +static bool armv8pmu_is_in_avoid_pmccntr_cpus(void)
> > +{
> > + return false;
> > +}
> > +#endif
> > +
> > struct armv8pmu_probe_info {
> > struct arm_pmu *pmu;
> > bool present;
> > @@ -1348,6 +1378,13 @@ static void __armv8pmu_probe_pmu(void
> *info)
> > else
> > cpu_pmu->reg_pmmir = 0;
> >
> > + /*
> > + * On some CPUs, PMCCNTR_EL0 does not match the behavior of
> CPU_CYCLES
> > + * programmable counter, so avoid routing cycles through PMCCNTR_EL0
> to
> > + * prevent inconsistency in the results.
> > + */
> > + cpu_pmu->avoid_pmccntr |= armv8pmu_is_in_avoid_pmccntr_cpus();
>
> Do we also want to hide the cycle counter from userspace? It sounds like
> it's going to get very confused if it tries to use it...
>
Makes sense. I tried making the change on v5.
Please check https://lore.kernel.org/linux-arm-kernel/20260608234135.1856911-1-bwicaksono@nvidia.com/T/#u
Thanks,
Besar
^ permalink raw reply
* [PATCH v5] perf/arm_pmu: Skip PMCCNTR_EL0 on NVIDIA Olympus
From: Besar Wicaksono @ 2026-06-08 23:41 UTC (permalink / raw)
To: will, mark.rutland, james.clark, yangyccccc
Cc: linux-arm-kernel, linux-kernel, linux-tegra, treding, jonathanh,
vsethi, rwiley, sdonthineni, mochs, nirmoyd, skelley,
Besar Wicaksono
The PMCCNTR_EL0 in NVIDIA Olympus CPU may increment while
in WFI/WFE, which does not align with counting CPU_CYCLES
on a programmable counter. Add a MIDR range entry and refuse
PMCCNTR_EL0 for cycle events on affected parts so perf does
not mix the two behaviors.
Also keep PMCCNTR_EL0 unavailable to EL0 direct counter reads
on affected CPUs. When userspace counter access is enabled,
avoid setting PMUSERENR_EL0.CR for PMUs that must avoid
PMCCNTR_EL0, while still allowing direct reads from programmable
event counters. For 64-bit userspace CPU_CYCLES events on PMUs
without native long event counters, reject the event if the only
valid direct-read path would be PMCCNTR_EL0.
Signed-off-by: Besar Wicaksono <bwicaksono@nvidia.com>
---
Changes from v1:
* add CONFIG_ARM64 check to fix build error found by kernel test robot
* add explicit include of <asm/cputype.h>
v1: https://lore.kernel.org/linux-arm-kernel/20260406232034.2566133-1-bwicaksono@nvidia.com/
Changes from v2:
* Move the Olympus PMCCNTR avoidance check from arm_pmuv3.c to the
common arm_pmu registration path.
* Replace the PMUv3-only has_smt flag with avoid_pmccntr, covering both
the existing SMT restriction and the Olympus MIDR restriction.
* Use the cached per-CPU MIDR from cpu_data instead of calling
is_midr_in_range_list() from armv8pmu_can_use_pmccntr().
* Add the required asm/cpu.h include for cpu_data.
v2: https://lore.kernel.org/linux-arm-kernel/20260421203856.3539186-1-bwicaksono@nvidia.com/#t
Changes from v3:
* Move avoidance check based on MIDR to __armv8pmu_probe_pmu() to make sure
the MIDR is retrieved from the correct online CPU.
v3: https://lore.kernel.org/linux-arm-kernel/20260429215614.1793131-1-bwicaksono@nvidia.com/
Changes from v4:
* Avoid granting PMCCNTR_EL0 direct userspace access by leaving
PMUSERENR_EL0.CR clear on PMUs that must avoid PMCCNTR_EL0.
* Keep direct userspace access available for programmable event counters.
* Reject 64-bit userspace CPU_CYCLES events on PMUs without native long
counters when the only valid direct-read path would be PMCCNTR_EL0.
* Expand the Olympus comment to describe the mismatch with programmable
CPU_CYCLES counters.
v4: https://lore.kernel.org/linux-arm-kernel/20260504175204.3122979-1-bwicaksono@nvidia.com/
---
drivers/perf/arm_pmu.c | 7 +++-
drivers/perf/arm_pmuv3.c | 64 +++++++++++++++++++++++++++++++-----
include/linux/perf/arm_pmu.h | 2 +-
3 files changed, 62 insertions(+), 11 deletions(-)
diff --git a/drivers/perf/arm_pmu.c b/drivers/perf/arm_pmu.c
index 939bcbd433aa..aa1dac0b440f 100644
--- a/drivers/perf/arm_pmu.c
+++ b/drivers/perf/arm_pmu.c
@@ -931,8 +931,13 @@ int armpmu_register(struct arm_pmu *pmu)
/*
* By this stage we know our supported CPUs on either DT/ACPI platforms,
* detect the SMT implementation.
+ * On SMT CPUs, the PMCCNTR_EL0 increments from the processor clock rather
+ * than the PE clock (ARM DDI0487 L.b D13.1.3) which means it'll continue
+ * counting on a WFI PE if one of its SMT sibling is not idle on a
+ * multi-threaded implementation. So don't use it on SMT cores.
*/
- pmu->has_smt = topology_core_has_smt(cpumask_first(&pmu->supported_cpus));
+ pmu->avoid_pmccntr |=
+ topology_core_has_smt(cpumask_first(&pmu->supported_cpus));
if (!pmu->set_event_filter)
pmu->pmu.capabilities |= PERF_PMU_CAP_NO_EXCLUDE;
diff --git a/drivers/perf/arm_pmuv3.c b/drivers/perf/arm_pmuv3.c
index 8014ff766cff..6d4d57342352 100644
--- a/drivers/perf/arm_pmuv3.c
+++ b/drivers/perf/arm_pmuv3.c
@@ -8,6 +8,7 @@
* This code is based heavily on the ARMv7 perf event code.
*/
+#include <asm/cputype.h>
#include <asm/irq_regs.h>
#include <asm/perf_event.h>
#include <asm/virt.h>
@@ -795,6 +796,7 @@ static void armv8pmu_disable_user_access(void)
static void armv8pmu_enable_user_access(struct arm_pmu *cpu_pmu)
{
int i;
+ u64 userenr = ARMV8_PMU_USERENR_ER | ARMV8_PMU_USERENR_UEN;
struct pmu_hw_events *cpuc = this_cpu_ptr(cpu_pmu->hw_events);
if (is_pmuv3p9(cpu_pmu->pmuver)) {
@@ -817,7 +819,10 @@ static void armv8pmu_enable_user_access(struct arm_pmu *cpu_pmu)
}
}
- update_pmuserenr(ARMV8_PMU_USERENR_ER | ARMV8_PMU_USERENR_CR | ARMV8_PMU_USERENR_UEN);
+ if (!cpu_pmu->avoid_pmccntr)
+ userenr |= ARMV8_PMU_USERENR_CR;
+
+ update_pmuserenr(userenr);
}
static void armv8pmu_enable_event(struct perf_event *event)
@@ -1002,13 +1007,7 @@ static bool armv8pmu_can_use_pmccntr(struct pmu_hw_events *cpuc,
if (has_branch_stack(event))
return false;
- /*
- * The PMCCNTR_EL0 increments from the processor clock rather than
- * the PE clock (ARM DDI0487 L.b D13.1.3) which means it'll continue
- * counting on a WFI PE if one of its SMT sibling is not idle on a
- * multi-threaded implementation. So don't use it on SMT cores.
- */
- if (cpu_pmu->has_smt)
+ if (cpu_pmu->avoid_pmccntr)
return false;
return true;
@@ -1250,7 +1249,8 @@ static int __armv8_pmuv3_map_event(struct perf_event *event,
if (!(event->attach_state & PERF_ATTACH_TASK))
return -EINVAL;
if (armv8pmu_event_is_64bit(event) &&
- (hw_event_id != ARMV8_PMUV3_PERFCTR_CPU_CYCLES) &&
+ (hw_event_id != ARMV8_PMUV3_PERFCTR_CPU_CYCLES ||
+ armpmu->avoid_pmccntr) &&
!armv8pmu_has_long_event(armpmu))
return -EOPNOTSUPP;
@@ -1299,6 +1299,45 @@ static int armv8_vulcan_map_event(struct perf_event *event)
&armv8_vulcan_perf_cache_map);
}
+#ifdef CONFIG_ARM64
+/*
+ * List of CPUs that should avoid using PMCCNTR_EL0.
+ */
+static struct midr_range armv8pmu_avoid_pmccntr_cpus[] = {
+ /*
+ * NVIDIA Olympus may expose different WFI/WFE behaviour between the
+ * PMCCNTR_EL0 and the CPU_CYCLES event on programmable counters.
+ * While the CPU is in WFI/WFE state, the PMCCNTR_EL0 may still increment
+ * but the programmable counter may not. This is an implementation specific
+ * behavior and not an erratum. Perf assumes those two paths are
+ * interchangeable, so avoid using PMCCNTR_EL0 for CPU_CYCLES event.
+ *
+ * From ARM DDI0487 D14.4:
+ * It is IMPLEMENTATION SPECIFIC whether CPU_CYCLES and PMCCNTR count
+ * when the PE is in WFI or WFE state, even if the clocks are not stopped.
+ *
+ * From ARM DDI0487 D24.5.2:
+ * All counters are subject to any changes in clock frequency, including
+ * clock stopping caused by the WFI and WFE instructions.
+ * This means that it is CONSTRAINED UNPREDICTABLE whether or not
+ * PMCCNTR_EL0 continues to increment when clocks are stopped by WFI and
+ * WFE instructions.
+ */
+ MIDR_ALL_VERSIONS(MIDR_NVIDIA_OLYMPUS),
+ {}
+};
+
+static bool armv8pmu_is_in_avoid_pmccntr_cpus(void)
+{
+ return is_midr_in_range_list(armv8pmu_avoid_pmccntr_cpus);
+}
+#else
+static bool armv8pmu_is_in_avoid_pmccntr_cpus(void)
+{
+ return false;
+}
+#endif
+
struct armv8pmu_probe_info {
struct arm_pmu *pmu;
bool present;
@@ -1348,6 +1387,13 @@ static void __armv8pmu_probe_pmu(void *info)
else
cpu_pmu->reg_pmmir = 0;
+ /*
+ * On some CPUs, PMCCNTR_EL0 does not match the behavior of CPU_CYCLES
+ * programmable counter, so avoid routing cycles through PMCCNTR_EL0 to
+ * prevent inconsistency in the results.
+ */
+ cpu_pmu->avoid_pmccntr |= armv8pmu_is_in_avoid_pmccntr_cpus();
+
brbe_probe(cpu_pmu);
}
diff --git a/include/linux/perf/arm_pmu.h b/include/linux/perf/arm_pmu.h
index 52b37f7bdbf9..02d2c7f45b52 100644
--- a/include/linux/perf/arm_pmu.h
+++ b/include/linux/perf/arm_pmu.h
@@ -119,7 +119,7 @@ struct arm_pmu {
/* PMUv3 only */
int pmuver;
- bool has_smt;
+ bool avoid_pmccntr;
u64 reg_pmmir;
u64 reg_brbidr;
#define ARMV8_PMUV3_MAX_COMMON_EVENTS 0x40
--
2.43.0
^ permalink raw reply related
* Re: -next boot failures during KVM setup
From: Nathan Chancellor @ 2026-06-08 23:27 UTC (permalink / raw)
To: Ard Biesheuvel
Cc: Marc Zyngier, Mark Brown, Will Deacon, Catalin Marinas,
Oliver Upton, Aishwarya.TCV, linux-arm-kernel
In-Reply-To: <8eac5e73-282d-4c72-b726-0c5c82fc81f0@app.fastmail.com>
On Mon, Jun 08, 2026 at 10:56:12PM +0200, Ard Biesheuvel wrote:
> Haven't seen this myself, surprisingly, but yeah, this is obviously related.
>
> By now, I am wondering if unmapping that region entirely is really worth the
> hassle, or whether we'd be better off just remapping it read-only.
>
> Given we're at -rc7, I'd lean towards dropping the whole branch for now, or
> alternatively, only drop/revert "arm64: mm: Unmap kernel data/bss entirely from the
> linear map" (and its followup fix "arm64: mm: Defer remap of linear alias of
> data/bss") so that the region always remains readable via the linear map.
FWIW, I can confirm that "arm64: mm: Unmap kernel data/bss entirely from
the linear map" is the culprit for this particular issue based on my
bisect. Reverting those two changes on top of next-20260608 avoids the
issue.
--
Cheers,
Nathan
^ permalink raw reply
* Re: [v7 PATCH] arm64: mm: show direct mapping use in /proc/meminfo
From: Yang Shi @ 2026-06-08 22:47 UTC (permalink / raw)
To: Will Deacon
Cc: catalin.marinas, ryan.roberts, cl, linux-arm-kernel, linux-kernel
In-Reply-To: <1252b93e-0c6b-4e33-9bf9-e42cde5ba0d2@os.amperecomputing.com>
On 6/2/26 1:38 PM, Yang Shi wrote:
>
>
> On 6/2/26 7:51 AM, Will Deacon wrote:
>> On Tue, May 19, 2026 at 09:36:57AM -0700, Yang Shi wrote:
>>> Since commit a166563e7ec3 ("arm64: mm: support large block mapping when
>>> rodata=full"), the direct mapping may be split on some machines instead
>>> keeping static since boot. It makes more sense to show the direct
>>> mapping
>>> use in /proc/meminfo than before.
>>> This patch will make /proc/meminfo show the direct mapping use like the
>>> below (4K base page size):
>>> DirectMap4K: 94792 kB
>>> DirectMap64K: 134208 kB
>>> DirectMap2M: 1173504 kB
>>> DirectMap32M: 5636096 kB
>>> DirectMap1G: 529530880 kB
>>>
>>> Although just the machines which support BBML2_NOABORT can split the
>>> direct mapping, show it on all machines regardless of BBML2_NOABORT so
>>> that the users have consistent view in order to avoid confusion.
>>>
>>> Although ptdump also can tell the direct map use, but it needs to dump
>>> the whole kernel page table. It is costly and overkilling. It is also
>>> in debugfs which may not be enabled by all distros. So showing direct
>>> map use in /proc/meminfo seems more convenient and has less overhead.
>>>
>>> Signed-off-by: Yang Shi<yang@os.amperecomputing.com>
>>> ---
>>> arch/arm64/mm/mmu.c | 192
>>> +++++++++++++++++++++++++++++++++++++++-----
>>> 1 file changed, 171 insertions(+), 21 deletions(-)
>>>
>>> v7: * Rebased to v7.1-rc4
>>> * Changed "dm" to "lm" to follow ARM convention per Will
>>> * Used __is_lm_alias() instead of reinventing a new helper per
>>> Will
>> Thanks, but Sashiko has pointed out a few nasty issues:
>>
>> https://sashiko.dev/#/patchset/20260519163657.1259416-1-yang@os.amperecomputing.com
>>
>>
>> In particular, the potential for races updating the shared counters and
>> double-accounting of entries due to permission changes look like
>> interesting things to check.
>
> Hi Will,
>
> Thanks for reminding for Sashiko review. Please see the below response.
It has been one week. I have not seen any objection, so I will proceed
with v8.
Thanks,
Yang
>
> #1
>> When features like memfd_secret remove pages from the direct map by
>> calling
>> set_direct_map_invalid_noflush(), it clears the PTE_VALID bit via the
>> pageattr
>> infrastructure.
>> Since this patch doesn't hook into those callbacks or set_pte() to
>> invoke
>> lm_meminfo_sub(), could the unmapped memory continue to be accounted
>> for,
>> leading to a persistent mismatch between the actual direct map size
>> and the
>> reported statistics?
>
> The direct mapping counters in /proc/meminfo don't treat invalid
> direct mapping differently if I read the x86 code correctly, as long
> as the range is still mapped by page table regardless whether it is
> valid or not. The counters are just updated when the mapping is
> created, removed (for example, boot stage or hot plug/unplug), split
> and collapsed. It seems like transient invalid direct mapping is not
> considered as "removed". And it seems not bother anyone.
>
> I think we should follow the semantics and keep the consistency. We
> can definitely make changes in the future if it turns out to be a real
> problem.
>
>
> #2
>> Could concurrent calls to functions like split_pmd() (e.g., via
>> set_memory_ro() or set_memory_rw() during BPF JIT allocations or module
>> loading) cause data races and lost updates here?
>> These updates use non-atomic read-modify-write operations, and
>> apply_to_page_range() only locks individual page tables rather than
>> using a
>> global lock.
>
> Sounds like a false positive. The direct mapping page table split is
> serialized by pgtable_split_lock.
>
>
> #3
>> Does this code, as well as similar sections in init_pmd() and
>> alloc_init_pud(), double-count memory regions when updating permissions
>> of existing direct mappings?
>> When functions like update_mapping_prot() change the permissions of
>> existing
>> valid direct map entries, this will unconditionally add the size
>> again without
>> checking if the entry was already present (e.g., checking pte_none()
>> first)
>> or subtracting the old size.
>
> Yes, it may double count when updating permission because updating
> permission reuses the same functions. It sounds not hard to address.
> We can check whether PUD/PMD/PTE is none. If it is none it means
> kernel is creating new page table, then we count it. If it not none,
> we skip accounting.
>
>
> #4
>> If a portion of a contiguous block is hot-removed, could this multiple
>> subtraction underflow the counter?
>> On ARM64, the memory hotplug block size can be smaller than a
>> contiguous block
>> size (e.g., CONT_PMD_SIZE is 16GB with 64K base pages). If a partial
>> chunk is
>> removed, this subtracts the full CONT_PMD_SIZE. However, it leaves the
>> PTE_CONT bit intact on the remaining valid PMDs.
>> A subsequent removal in the same contiguous block would see the PTE_CONT
>> bit again and subtract the full CONT_PMD_SIZE a second time,
>> underflowing the
>> counter.
>
> It sounds like a false positive to me. This case should not happen at
> all. We just can't unplug a portion of DIMM, right?
>
> For example, we plug a 16G dimm to the machine. We can offline a
> portion of it (at section granularity), but we can't unplug a portion
> of it, we just can unplug the whole dimm. The counters update happens
> when unplug.
>
> Thanks,
> Yang
>
>> Will
>
^ permalink raw reply
* Re: [PATCH] dt-bindings: pinctrl: mediatek: mt6795: document the slew-rate property
From: Linus Walleij @ 2026-06-08 22:46 UTC (permalink / raw)
To: Luca Leonardo Scorcia
Cc: linux-mediatek, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Matthias Brugger, AngeloGioacchino Del Regno, Sean Wang,
linux-gpio, devicetree, linux-kernel, linux-arm-kernel
In-Reply-To: <20260601152707.29039-1-l.scorcia@gmail.com>
On Mon, Jun 1, 2026 at 5:27 PM Luca Leonardo Scorcia
<l.scorcia@gmail.com> wrote:
> The driver for MT6795 pinctrl already supports the slew-rate property.
> Add its description to the documentation.
>
> Signed-off-by: Luca Leonardo Scorcia <l.scorcia@gmail.com>
Patch applied!
Yours,
Linus Walleij
^ permalink raw reply
* Re: [PATCHv2 2/3] watchdog: sama5d4: use platform_get_irq_optional()
From: Guenter Roeck @ 2026-06-08 22:44 UTC (permalink / raw)
To: Rosen Penev, linux-watchdog
Cc: Nicolas Ferre, Alexandre Belloni, Claudiu Beznea,
Wim Van Sebroeck, moderated list:ARM/Microchip (AT91) SoC support,
open list
In-Reply-To: <20260608200933.18669-3-rosenp@gmail.com>
On 6/8/26 13:09, Rosen Penev wrote:
> irq_of_parse_and_map() requires irq_dispose_mapping() on failure. Don't
> bother with it as platform_get_irq_optional() doesn't need it.
>
> Also handle EPROBE_DEFER.
>
That is misleading. irq_of_parse_and_map() did not return errors,
so this is not an "also" but made necessary by the use of
platform_get_irq_optional(). That means that replacing the
call with platform_get_irq_optional() is not a 1:1 replacement,
making its use risky without extensive testing.
A much safer solution is to add a call to devm_add_action_or_reset()
after successful irq_of_parse_and_map() and to call irq_dispose_mapping()
from its callback function.
Thanks,
Guenter
^ permalink raw reply
* Re: [PATCHv2 1/3] watchdog: sama5d4: fix shared IRQ and hardcoded timeout issues
From: Guenter Roeck @ 2026-06-08 22:35 UTC (permalink / raw)
To: Rosen Penev, linux-watchdog
Cc: Nicolas Ferre, Alexandre Belloni, Claudiu Beznea,
Wim Van Sebroeck, moderated list:ARM/Microchip (AT91) SoC support,
open list
In-Reply-To: <20260608200933.18669-2-rosenp@gmail.com>
On 6/8/26 13:09, Rosen Penev wrote:
> Fix three pre-existing issues in the sama5d4 watchdog driver:
>
> 1. Unsafe IRQF_SHARED | IRQF_NO_SUSPEND combination: The watchdog
> interrupt is a dedicated peripheral line, not shared with other
> devices.
>
Not addressed in this patch, and can not be addressed without testing
on real hardware. We'll have to leave that alone.
> 2. Unconditional IRQ_HANDLED on shared line: The handler returned
> IRQ_HANDLED even when the status register indicated no watchdog
> interrupt was pending. Return IRQ_NONE in that case so the kernel
> can properly detect spurious interrupts on the line.
>
> 3. Hardcoded 16-second timeout: sama5d4_wdt_init() unconditionally
> used WDT_DEFAULT_TIMEOUT (16s) for the hardware timeout, ignoring
> any timeout configured via device tree (watchdog_init_timeout) or
> userspace. Pass wdd->timeout to sama5d4_wdt_init() so the
> configured timeout is honored during probe and resume.
>
While I think this is a real problem, changing the code would require
testing on real hardware. We'll have to leave this alone.
Please resubmit, only fixing issue 2). Please list the other problems as
explicitly not fixed in the summary e-mail.
This also applies to the new problem regarding AT91_WDT_WDDIS vs.
AT91_SAM9X60_WDDIS. If that is a real problem, it can only be fixed
by someone with access to hardware and with chip knowledge.
Besides that, I would suggest to re-order the patches.
Patch 3 (the null pointer fix) should be first, followed by this patch.
Patch 2 should be last.
Thanks,
Guenter
^ permalink raw reply
* Re: [PATCH v9 6/7] pinctrl: s32cc: implement GPIO functionality
From: Linus Walleij @ 2026-06-08 22:33 UTC (permalink / raw)
To: Khristine Andreea Barbulescu
Cc: Linus Walleij, Bartosz Golaszewski, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Chester Lin, Matthias Brugger,
Ghennadi Procopciuc, Larisa Grigore, Lee Jones, Shawn Guo,
Sascha Hauer, Fabio Estevam, Dong Aisheng, Jacky Bai,
Greg Kroah-Hartman, Rafael J. Wysocki, Srinivas Kandagatla,
Alberto Ruiz, Christophe Lizzi, devicetree, Enric Balletbo,
Eric Chanudet, imx, linux-arm-kernel, linux-gpio, linux-kernel,
NXP S32 Linux Team, Pengutronix Kernel Team, Vincent Guittot
In-Reply-To: <48494e7b-4cba-4372-9090-f40240d820c4@oss.nxp.com>
Hi Khristine,
On Tue, Jun 2, 2026 at 10:05 AM Khristine Andreea Barbulescu
<khristineandreea.barbulescu@oss.nxp.com> wrote:
> The new version (v10) has been updated to use gpio-regmap, with a virtual
> regmap bridge dispatching GPIO accesses to the underlying SIUL2 register
> blocks.
>
> I am not fully convinced this is the cleanest model, though.
> SIUL2 does not expose GPIO as one regular register space: direction is in
> MSCR, input values are read from PGPDI, and output values are written through
> PGPDO. These are backed by separate regmaps in the driver, while gpio-regmap
> expects a single regmap.
OK I did miss that detail earlier, I definitely thought it was using a single
regmap.
> So the current path becomes:
> gpio-regmap -> virtual regmap -> MSCR/PGPDI/PGPDO regmap
>
> The version was updated this way so we can review the approach on top of the
> current code. If this is still the preferred direction, it can be polished
> further. Otherwise, I think direct gpio_chip callbacks using the existing regmap
> helpers might be a simpler fit for this hardware.
>
> What do you think would be the preferred direction for the next revision?
I'm pretty much happy with either version.
I see your point as to why you don't want to use gpio-regmap.
I also think the virtual regmap thing looks pretty OK, it's complex
but the driver is complex anyway.
What could make the gpio-regmap approach is that it will probably
get extended with get/set_multiple() at some point and then you
will get that improvement for free.
But I think you are the best person to choose what to use here,
if you don't think the virtual regmap looks good, then trust your
intuition and go back to the old design.
Yours,
Linus Walleij
^ permalink raw reply
* [soc:soc/arm] BUILD SUCCESS f6f84276c6cf2a257a8054137e49b5f37e19f27b
From: kernel test robot @ 2026-06-08 22:30 UTC (permalink / raw)
To: Linus Walleij; +Cc: linux-arm-kernel, arm
tree/branch: https://git.kernel.org/pub/scm/linux/kernel/git/soc/soc.git soc/arm
branch HEAD: f6f84276c6cf2a257a8054137e49b5f37e19f27b Merge tag 'samsung-soc-7.2' of https://git.kernel.org/pub/scm/linux/kernel/git/krzk/linux into soc/arm
elapsed time: 7302m
configs tested: 2
configs skipped: 246
The following configs have been built successfully.
More configs may be tested in the coming days.
tested configs:
arm allnoconfig clang-23
arm allyesconfig gcc-16.1.0
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply
* Re: [PATCH v5 0/4] Enable sysfs module symlink for more built-in drivers
From: Danilo Krummrich @ 2026-06-08 22:24 UTC (permalink / raw)
To: Shashank Balaji
Cc: Suzuki K Poulose, James Clark, Alexander Shishkin,
Greg Kroah-Hartman, Rafael J . Wysocki, Danilo Krummrich,
Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron,
Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross,
Jonathan Corbet, Shuah Khan, Luis Chamberlain, Petr Pavlu,
Daniel Gomez, Sami Tolvanen, Aaron Tomlin, Mike Leach, Leo Yan,
Thierry Reding, Jonathan Hunter, Rahul Bukte, linux-kernel,
coresight, linux-arm-kernel, driver-core, rust-for-linux,
linux-doc, Daniel Palmer, Tim Bird, linux-modules, linux-tegra,
Sumit Gupta
In-Reply-To: <20260518-acpi_mod_name-v5-0-705ccc430885@sony.com>
On Mon, 18 May 2026 19:19:56 +0900, Shashank Balaji wrote:
> [PATCH v5 0/4] Enable sysfs module symlink for more built-in drivers
Applied, thanks!
Branch: driver-core-testing
Tree: git://git.kernel.org/pub/scm/linux/kernel/git/driver-core/driver-core.git
[1/4] soc/tegra: cbb: Move driver registration from pure_initcall to core_initcall
commit: cd6e95e7ab29
[2/4] kernel: param: initialize module_kset in a pure_initcall
commit: c82dfce47833
[3/4] coresight: pass THIS_MODULE implicitly through a macro
commit: efc22b3f89a3
[4/4] driver core: platform: set mod_name in driver registration
commit: a7a7dc5c46a0
The patches will appear in the next linux-next integration (typically within 24
hours on weekdays).
The patches are in the driver-core-testing branch and will be promoted to
driver-core-next after validation.
^ permalink raw reply
* [PATCH v4 phy-next 15/16] phy: lynx-10g: new driver
From: Vladimir Oltean @ 2026-06-08 22:17 UTC (permalink / raw)
To: linux-phy
Cc: Ioana Ciornei, Vinod Koul, Neil Armstrong, Tanjeff Moos,
linux-kernel, devicetree, Conor Dooley, Krzysztof Kozlowski,
Rob Herring, linux-arm-kernel, chleroy, linuxppc-dev
In-Reply-To: <20260608221710.1572971-1-vladimir.oltean@nxp.com>
Introduce a driver for the networking lanes of the 10G Lynx SerDes
block, present on the majority of Layerscape and QorIQ (Freescale/NXP)
SoCs.
As with the 28G Lynx, the SerDes lanes come pre-initialized out of
reset and the consumers use them that way outside the Generic PHY
framework (for networking, the static configuration remains for the
entire SoC lifetime, whereas for SATA and PCIe, the hardware
reconfigures itself automatically for other link speeds).
The need for the Generic PHY framework comes specifically for networking
use cases where a static lane configuration is not sufficient. For
example a network MAC is connected to an SFP cage, where various SFP or
SFP+ modules can be connected. Each of them may require a different
SerDes protocol (SGMII, 1000Base-X, 10GBase-R), which phylink + sfp-bus
are responsible of figuring out. The phylink drivers are:
- enetc
- felix
- dpaa_eth (fman_memac)
- dpaa2-eth
- dpaa2-switch
and they all need to reconfigure the SerDes for the requested link mode,
using phy_set_mode_ext() (and phy_validate() to see if it is supported
in the first place).
Note that SerDes 2 on LS1088A is exclusively non-networking, so there is
currently no need for this driver. Therefore we skip matching on its
compatible string and do not probe on that device.
Co-developed-by: Ioana Ciornei <ioana.ciornei@nxp.com>
Signed-off-by: Ioana Ciornei <ioana.ciornei@nxp.com>
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
Cc: devicetree@vger.kernel.org
Cc: Conor Dooley <conor+dt@kernel.org>
Cc: Krzysztof Kozlowski <krzk+dt@kernel.org>
Cc: Rob Herring <robh@kernel.org>
Cc: linux-arm-kernel@lists.infradead.org
Cc: chleroy@kernel.org
Cc: linuxppc-dev@lists.ozlabs.org
v3->v4: none
v2->v3:
- fix lynx_10g_power_on() procedure
- include <linux/of.h> instead of <linux/of_device.h>
- fix build warning introduced in v2 in lynx_10g_lane_set_nrate()
v1->v2:
- move lynx_lane_restrict_fixed_mode_change() to lynx-core, even though
the 28G Lynx as instantiated in LX2 does not have QSGMII.
- lynx_10g_validate() now calls the new lynx_phy_mode_to_lane_mode()
which does verify that the current lane mode is supported
- avoid line size checkpatch warnings in lynx_10g_lane_set_nrate() by
saving the nrate to a variable and calling lynx_lane_rmw() only once
- remove redundant "if (!lane->powered_up)" checks from
lynx_10g_lane_halt() and lynx_10g_lane_reset() - also checked at
the only call site, lynx_10g_set_mode(), as in lynx-28g
- expand CC list (flagged by Patchwork)
---
drivers/phy/freescale/Kconfig | 10 +
drivers/phy/freescale/Makefile | 1 +
drivers/phy/freescale/phy-fsl-lynx-10g.c | 1278 +++++++++++++++++++++
drivers/phy/freescale/phy-fsl-lynx-core.c | 38 +
drivers/phy/freescale/phy-fsl-lynx-core.h | 4 +
include/soc/fsl/phy-fsl-lynx.h | 27 +
6 files changed, 1358 insertions(+)
create mode 100644 drivers/phy/freescale/phy-fsl-lynx-10g.c
diff --git a/drivers/phy/freescale/Kconfig b/drivers/phy/freescale/Kconfig
index ac575d531db7..5bf3864fbe64 100644
--- a/drivers/phy/freescale/Kconfig
+++ b/drivers/phy/freescale/Kconfig
@@ -54,6 +54,16 @@ endif
config PHY_FSL_LYNX_CORE
tristate
+config PHY_FSL_LYNX_10G
+ tristate "Freescale Layerscape Lynx 10G SerDes PHY support"
+ depends on OF
+ depends on ARCH_LAYERSCAPE || COMPILE_TEST
+ select GENERIC_PHY
+ select PHY_FSL_LYNX_CORE
+ help
+ Enable this to add support for the Lynx 10G SerDes PHY as found on
+ NXP's Layerscape platform such as LS1088A or LS1028A.
+
config PHY_FSL_LYNX_28G
tristate "Freescale Layerscape Lynx 28G SerDes PHY support"
depends on OF
diff --git a/drivers/phy/freescale/Makefile b/drivers/phy/freescale/Makefile
index d7aa62cdeb39..5b0e180d6972 100644
--- a/drivers/phy/freescale/Makefile
+++ b/drivers/phy/freescale/Makefile
@@ -5,5 +5,6 @@ obj-$(CONFIG_PHY_MIXEL_MIPI_DPHY) += phy-fsl-imx8-mipi-dphy.o
obj-$(CONFIG_PHY_FSL_IMX8M_PCIE) += phy-fsl-imx8m-pcie.o
obj-$(CONFIG_PHY_FSL_IMX8QM_HSIO) += phy-fsl-imx8qm-hsio.o
obj-$(CONFIG_PHY_FSL_LYNX_CORE) += phy-fsl-lynx-core.o
+obj-$(CONFIG_PHY_FSL_LYNX_10G) += phy-fsl-lynx-10g.o
obj-$(CONFIG_PHY_FSL_LYNX_28G) += phy-fsl-lynx-28g.o
obj-$(CONFIG_PHY_FSL_SAMSUNG_HDMI_PHY) += phy-fsl-samsung-hdmi.o
diff --git a/drivers/phy/freescale/phy-fsl-lynx-10g.c b/drivers/phy/freescale/phy-fsl-lynx-10g.c
new file mode 100644
index 000000000000..7dd5d94b51cf
--- /dev/null
+++ b/drivers/phy/freescale/phy-fsl-lynx-10g.c
@@ -0,0 +1,1278 @@
+// SPDX-License-Identifier: GPL-2.0+
+/* Copyright 2021-2026 NXP */
+
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/phy.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+#include <linux/workqueue.h>
+
+#include "phy-fsl-lynx-core.h"
+
+/* SoC IP wrapper for protocol converters */
+#define PCCR8 0x220
+#define PCCR8_SGMIIa_KX BIT(3)
+#define PCCR8_SGMIIa_CFG BIT(0)
+
+#define PCCR9 0x224
+#define PCCR9_QSGMIIa_CFG BIT(0)
+#define PCCR9_QXGMIIa_CFG BIT(0)
+
+#define PCCRB 0x22c
+#define PCCRB_XFIa_CFG BIT(0)
+#define PCCRB_SXGMIIa_CFG BIT(0)
+
+#define SGMII_CFG(id) (28 - (id) * 4)
+#define QSGMII_CFG(id) (28 - (id) * 4)
+#define SXGMII_CFG(id) (28 - (id) * 4)
+#define QXGMII_CFG(id) (12 - (id) * 4)
+#define XFI_CFG(id) (28 - (id) * 4)
+
+#define CR(x) ((x) * 4)
+
+#define A 0
+#define B 1
+#define C 2
+#define D 3
+#define E 4
+#define F 5
+#define G 6
+#define H 7
+
+#define SGMIIaCR0(id) (0x1800 + (id) * 0x10)
+#define QSGMIIaCR0(id) (0x1880 + (id) * 0x10)
+#define XAUIaCR0(id) (0x1900 + (id) * 0x10)
+#define XFIaCR0(id) (0x1980 + (id) * 0x10)
+#define SXGMIIaCR0(id) (0x1a80 + (id) * 0x10)
+#define QXGMIIaCR0(id) (0x1b00 + (id) * 0x20)
+
+#define SGMIIaCR0_RST_SGM BIT(31)
+#define SGMIIaCR0_RST_SGM_OFF SGMIIaCR0_RST_SGM
+#define SGMIIaCR0_RST_SGM_ON 0
+#define SGMIIaCR0_PD_SGM BIT(30)
+#define SGMIIaCR1_SGPCS_EN BIT(11)
+#define SGMIIaCR1_SGPCS_DIS 0x0
+
+#define QSGMIIaCR0_RST_QSGM BIT(31)
+#define QSGMIIaCR0_RST_QSGM_OFF QSGMIIaCR0_RST_QSGM
+#define QSGMIIaCR0_RST_QSGM_ON 0
+#define QSGMIIaCR0_PD_QSGM BIT(30)
+
+/* Per PLL registers */
+#define PLLnCR0(pll) ((pll) * 0x20 + 0x4)
+
+#define PLLnCR0_POFF BIT(31)
+
+#define PLLnCR0_REFCLK_SEL GENMASK(30, 28)
+#define PLLnCR0_REFCLK_SEL_100MHZ 0x0
+#define PLLnCR0_REFCLK_SEL_125MHZ 0x1
+#define PLLnCR0_REFCLK_SEL_156MHZ 0x2
+#define PLLnCR0_REFCLK_SEL_150MHZ 0x3
+#define PLLnCR0_REFCLK_SEL_161MHZ 0x4
+#define PLLnCR0_PLL_LCK BIT(23)
+#define PLLnCR0_FRATE_SEL GENMASK(19, 16)
+#define PLLnCR0_FRATE_5G 0x0
+#define PLLnCR0_FRATE_5_15625G 0x6
+#define PLLnCR0_FRATE_4G 0x7
+#define PLLnCR0_FRATE_3_125G 0x9
+#define PLLnCR0_FRATE_3G 0xa
+
+/* Per SerDes lane registers */
+
+/* Lane a Protocol Select status register */
+#define LNaPSSR0(lane) (0x100 + (lane) * 0x20)
+#define LNaPSSR0_TYPE GENMASK(30, 26)
+#define LNaPSSR0_IS_QUAD GENMASK(25, 24)
+#define LNaPSSR0_MAC GENMASK(19, 16)
+#define LNaPSSR0_PCS GENMASK(10, 8)
+#define LNaPSSR0_LANE GENMASK(2, 0)
+
+/* Lane a General Control Register */
+#define LNaGCR0(lane) (0x800 + (lane) * 0x40 + 0x0)
+#define LNaGCR0_RPLL_PLLF BIT(31)
+#define LNaGCR0_RPLL_PLLS 0x0
+#define LNaGCR0_RPLL_MSK BIT(31)
+#define LNaGCR0_RRAT_SEL GENMASK(29, 28)
+#define LNaGCR0_TRAT_SEL GENMASK(25, 24)
+#define LNaGCR0_TPLL_PLLF BIT(27)
+#define LNaGCR0_TPLL_PLLS 0x0
+#define LNaGCR0_TPLL_MSK BIT(27)
+#define LNaGCR0_RRST_OFF LNaGCR0_RRST
+#define LNaGCR0_TRST_OFF LNaGCR0_TRST
+#define LNaGCR0_RRST_ON 0x0
+#define LNaGCR0_TRST_ON 0x0
+#define LNaGCR0_RRST BIT(22)
+#define LNaGCR0_TRST BIT(21)
+#define LNaGCR0_RX_PD BIT(20)
+#define LNaGCR0_TX_PD BIT(19)
+#define LNaGCR0_IF20BIT_EN BIT(18)
+#define LNaGCR0_PROTS GENMASK(11, 7)
+
+#define LNaGCR1(lane) (0x800 + (lane) * 0x40 + 0x4)
+#define LNaGCR1_RDAT_INV BIT(31)
+#define LNaGCR1_TDAT_INV BIT(30)
+#define LNaGCR1_OPAD_CTL BIT(26)
+#define LNaGCR1_REIDL_TH GENMASK(22, 20)
+#define LNaGCR1_REIDL_EX_SEL GENMASK(19, 18)
+#define LNaGCR1_REIDL_ET_SEL GENMASK(17, 16)
+#define LNaGCR1_REIDL_EX_MSB BIT(15)
+#define LNaGCR1_REIDL_ET_MSB BIT(14)
+#define LNaGCR1_REQ_CTL_SNP BIT(13)
+#define LNaGCR1_REQ_CDR_SNP BIT(12)
+#define LNaGCR1_TRSTDIR BIT(7)
+#define LNaGCR1_REQ_BIN_SNP BIT(6)
+#define LNaGCR1_ISLEW_RCTL GENMASK(5, 4)
+#define LNaGCR1_OSLEW_RCTL GENMASK(1, 0)
+
+#define LNaRECR0(lane) (0x800 + (lane) * 0x40 + 0x10)
+#define LNaRECR0_RXEQ_BST BIT(28)
+#define LNaRECR0_GK2OVD GENMASK(27, 24)
+#define LNaRECR0_GK3OVD GENMASK(19, 16)
+#define LNaRECR0_GK2OVD_EN BIT(15)
+#define LNaRECR0_GK3OVD_EN BIT(14)
+#define LNaRECR0_OSETOVD_EN BIT(13)
+#define LNaRECR0_BASE_WAND GENMASK(11, 10)
+#define LNaRECR0_OSETOVD GENMASK(6, 0)
+
+#define LNaTECR0(lane) (0x800 + (lane) * 0x40 + 0x18)
+#define LNaTECR0_TEQ_TYPE GENMASK(29, 28)
+#define LNaTECR0_SGN_PREQ BIT(26)
+#define LNaTECR0_RATIO_PREQ GENMASK(25, 22)
+#define LNaTECR0_SGN_POST1Q BIT(21)
+#define LNaTECR0_RATIO_PST1Q GENMASK(20, 16)
+#define LNaTECR0_ADPT_EQ GENMASK(13, 8)
+#define LNaTECR0_AMP_RED GENMASK(5, 0)
+
+#define LNaTTLCR0(lane) (0x800 + (lane) * 0x40 + 0x20)
+#define LNaTTLCR1(lane) (0x800 + (lane) * 0x40 + 0x24)
+#define LNaTTLCR2(lane) (0x800 + (lane) * 0x40 + 0x28)
+
+#define LNaTCSR3(lane) (0x800 + (lane) * 0x40 + 0x3C)
+#define LNaTCSR3_CDR_LCK BIT(27)
+
+enum lynx_10g_rat_sel {
+ RAT_SEL_FULL = 0x0,
+ RAT_SEL_HALF = 0x1,
+ RAT_SEL_QUARTER = 0x2,
+ RAT_SEL_DOUBLE = 0x3,
+};
+
+enum lynx_10g_eq_type {
+ EQ_TYPE_NO_EQ = 0,
+ EQ_TYPE_2TAP = 1,
+ EQ_TYPE_3TAP = 2,
+};
+
+enum lynx_10g_proto_sel {
+ PROTO_SEL_PCIE = 0,
+ PROTO_SEL_SGMII_BASEX_KX_QSGMII = 1,
+ PROTO_SEL_SATA = 2,
+ PROTO_SEL_XAUI = 4,
+ PROTO_SEL_XFI_10GBASER_KR_SXGMII = 0xa,
+};
+
+struct lynx_10g_proto_conf {
+ int proto_sel;
+ int if20bit_en;
+ int reidl_th;
+ int reidl_et_msb;
+ int reidl_et_sel;
+ int reidl_ex_msb;
+ int reidl_ex_sel;
+ int islew_rctl;
+ int oslew_rctl;
+ int rxeq_bst;
+ int gk2ovd;
+ int gk3ovd;
+ int gk2ovd_en;
+ int gk3ovd_en;
+ int base_wand;
+ int teq_type;
+ int sgn_preq;
+ int ratio_preq;
+ int sgn_post1q;
+ int ratio_post1q;
+ int adpt_eq;
+ int amp_red;
+ int ttlcr0;
+};
+
+static const struct lynx_10g_proto_conf lynx_10g_proto_conf[LANE_MODE_MAX] = {
+ [LANE_MODE_1000BASEX_SGMII] = {
+ .proto_sel = PROTO_SEL_SGMII_BASEX_KX_QSGMII,
+ .reidl_th = 1,
+ .reidl_ex_sel = 3,
+ .reidl_et_msb = 1,
+ .islew_rctl = 1,
+ .oslew_rctl = 1,
+ .gk2ovd = 15,
+ .gk3ovd = 15,
+ .gk2ovd_en = 1,
+ .gk3ovd_en = 1,
+ .teq_type = EQ_TYPE_NO_EQ,
+ .adpt_eq = 48,
+ .amp_red = 6,
+ .ttlcr0 = 0x39000400,
+ },
+ [LANE_MODE_2500BASEX] = {
+ .proto_sel = PROTO_SEL_SGMII_BASEX_KX_QSGMII,
+ .islew_rctl = 2,
+ .oslew_rctl = 2,
+ .teq_type = EQ_TYPE_2TAP,
+ .sgn_post1q = 1,
+ .ratio_post1q = 6,
+ .adpt_eq = 48,
+ .ttlcr0 = 0x00000400,
+ },
+ [LANE_MODE_QSGMII] = {
+ .proto_sel = PROTO_SEL_SGMII_BASEX_KX_QSGMII,
+ .islew_rctl = 1,
+ .oslew_rctl = 1,
+ .teq_type = EQ_TYPE_2TAP,
+ .sgn_post1q = 1,
+ .ratio_post1q = 6,
+ .adpt_eq = 48,
+ .amp_red = 2,
+ .ttlcr0 = 0x00000400,
+ },
+ [LANE_MODE_10G_QXGMII] = {
+ .proto_sel = PROTO_SEL_XFI_10GBASER_KR_SXGMII,
+ .if20bit_en = 1,
+ .islew_rctl = 1,
+ .oslew_rctl = 1,
+ .base_wand = 1,
+ .teq_type = EQ_TYPE_NO_EQ,
+ .adpt_eq = 48,
+ .ttlcr0 = 0x00000400,
+ },
+ [LANE_MODE_USXGMII] = {
+ .proto_sel = PROTO_SEL_XFI_10GBASER_KR_SXGMII,
+ .if20bit_en = 1,
+ .islew_rctl = 1,
+ .oslew_rctl = 1,
+ .base_wand = 1,
+ .teq_type = EQ_TYPE_NO_EQ,
+ .sgn_post1q = 1,
+ .adpt_eq = 48,
+ .ttlcr0 = 0x00000400,
+ },
+ [LANE_MODE_10GBASER] = {
+ .proto_sel = PROTO_SEL_XFI_10GBASER_KR_SXGMII,
+ .if20bit_en = 1,
+ .islew_rctl = 2,
+ .oslew_rctl = 2,
+ .rxeq_bst = 1,
+ .base_wand = 1,
+ .teq_type = EQ_TYPE_2TAP,
+ .sgn_post1q = 1,
+ .ratio_post1q = 3,
+ .adpt_eq = 48,
+ .amp_red = 7,
+ .ttlcr0 = 0x00000400,
+ },
+};
+
+static void lynx_10g_cdr_lock_check(struct lynx_lane *lane)
+{
+ u32 tcsr3 = lynx_lane_read(lane, LNaTCSR3);
+
+ if (tcsr3 & LNaTCSR3_CDR_LCK)
+ return;
+
+ dev_dbg(&lane->phy->dev,
+ "Lane %c CDR unlocked, resetting receiver...\n",
+ 'A' + lane->id);
+
+ lynx_lane_rmw(lane, LNaGCR0, LNaGCR0_RRST_ON, LNaGCR0_RRST);
+ usleep_range(1, 2);
+ lynx_lane_rmw(lane, LNaGCR0, LNaGCR0_RRST_OFF, LNaGCR0_RRST);
+
+ usleep_range(1, 2);
+}
+
+static void lynx_10g_pll_read_configuration(struct lynx_pll *pll)
+{
+ u32 val;
+
+ val = lynx_pll_read(pll, PLLnCR0);
+ pll->frate_sel = FIELD_GET(PLLnCR0_FRATE_SEL, val);
+ pll->refclk_sel = FIELD_GET(PLLnCR0_REFCLK_SEL, val);
+ pll->enabled = !(val & PLLnCR0_POFF);
+ pll->locked = !!(val & PLLnCR0_PLL_LCK);
+
+ if (!pll->enabled)
+ return;
+
+ switch (pll->frate_sel) {
+ case PLLnCR0_FRATE_5G:
+ /* 5GHz clock net */
+ __set_bit(LANE_MODE_1000BASEX_SGMII, pll->supported);
+ __set_bit(LANE_MODE_QSGMII, pll->supported);
+ break;
+ case PLLnCR0_FRATE_3_125G:
+ __set_bit(LANE_MODE_2500BASEX, pll->supported);
+ break;
+ case PLLnCR0_FRATE_5_15625G:
+ /* 10.3125GHz clock net */
+ __set_bit(LANE_MODE_10GBASER, pll->supported);
+ __set_bit(LANE_MODE_USXGMII, pll->supported);
+ __set_bit(LANE_MODE_10G_QXGMII, pll->supported);
+ break;
+ default:
+ break;
+ }
+}
+
+/* On LS1028A, SGMIIA_CFG, SGMIIB_CFG, and SGMIIC_CFG from PCCR8 have the
+ * ability to map either an ENETC PCS or a Felix switch PCS to the same lane.
+ * The PHY API lacks the capability to distinguish between one consumer and
+ * another, so we don't support changing the initial muxing done by the RCW.
+ * However, when disabling a PCS through PCCR8, we need to properly restore
+ * the original value to keep the same muxing, and for that we need to back
+ * it up (here).
+ */
+static void lynx_10g_backup_pccr_val(struct lynx_lane *lane)
+{
+ u32 val;
+ int err;
+
+ if (lane->mode == LANE_MODE_UNKNOWN)
+ return;
+
+ err = lynx_pccr_read(lane, lane->mode, &val);
+ if (err) {
+ dev_warn(&lane->phy->dev,
+ "The driver doesn't know how to access the PCCR for lane mode %s\n",
+ lynx_lane_mode_str(lane->mode));
+ lane->mode = LANE_MODE_UNKNOWN;
+ return;
+ }
+
+ lane->default_pccr[lane->mode] = val;
+
+ switch (lane->mode) {
+ case LANE_MODE_1000BASEX_SGMII:
+ case LANE_MODE_2500BASEX:
+ lane->default_pccr[LANE_MODE_1000BASEX_SGMII] = val & ~PCCR8_SGMIIa_KX;
+ lane->default_pccr[LANE_MODE_2500BASEX] = val & ~PCCR8_SGMIIa_KX;
+ break;
+ default:
+ break;
+ }
+}
+
+static bool lynx_10g_lane_is_3_125g(struct lynx_lane *lane)
+{
+ struct lynx_priv *priv = lane->priv;
+ struct lynx_pll *pll;
+ u32 gcr0;
+
+ gcr0 = lynx_lane_read(lane, LNaGCR0);
+
+ if (gcr0 & LNaGCR0_TPLL_PLLF)
+ pll = &priv->pll[0];
+ else
+ pll = &priv->pll[1];
+
+ if (pll->frate_sel != PLLnCR0_FRATE_3_125G)
+ return false;
+
+ if (FIELD_GET(LNaGCR0_TRAT_SEL, gcr0) != RAT_SEL_FULL ||
+ FIELD_GET(LNaGCR0_RRAT_SEL, gcr0) != RAT_SEL_FULL)
+ return false;
+
+ return true;
+}
+
+static void lynx_10g_lane_read_configuration(struct lynx_lane *lane)
+{
+ u32 pssr0 = lynx_lane_read(lane, LNaPSSR0);
+ struct lynx_priv *priv = lane->priv;
+ int proto;
+
+ proto = FIELD_GET(LNaPSSR0_TYPE, pssr0);
+ switch (proto) {
+ case PROTO_SEL_SGMII_BASEX_KX_QSGMII:
+ if (lynx_10g_lane_is_3_125g(lane))
+ lane->mode = LANE_MODE_2500BASEX;
+ else if (FIELD_GET(LNaPSSR0_IS_QUAD, pssr0))
+ lane->mode = LANE_MODE_QSGMII;
+ else
+ lane->mode = LANE_MODE_1000BASEX_SGMII;
+ break;
+ case PROTO_SEL_XFI_10GBASER_KR_SXGMII:
+ if (FIELD_GET(LNaPSSR0_IS_QUAD, pssr0))
+ lane->mode = LANE_MODE_10G_QXGMII;
+ else if (priv->info->quirks & LYNX_QUIRK_HAS_HARDCODED_USXGMII)
+ lane->mode = LANE_MODE_USXGMII;
+ else
+ lane->mode = LANE_MODE_10GBASER;
+ break;
+ case PROTO_SEL_PCIE:
+ case PROTO_SEL_SATA:
+ case PROTO_SEL_XAUI:
+ break;
+ default:
+ dev_warn(&lane->phy->dev, "Unknown lane protocol 0x%x\n",
+ proto);
+ }
+
+ lynx_10g_backup_pccr_val(lane);
+}
+
+static int ls1028a_get_pccr(enum lynx_lane_mode lane_mode, int lane,
+ struct lynx_pccr *pccr)
+{
+ switch (lane_mode) {
+ case LANE_MODE_1000BASEX_SGMII:
+ case LANE_MODE_2500BASEX:
+ pccr->offset = PCCR8;
+ pccr->width = 4;
+ pccr->shift = SGMII_CFG(lane);
+ break;
+ case LANE_MODE_QSGMII:
+ if (lane != 1)
+ return -EINVAL;
+
+ pccr->offset = PCCR9;
+ pccr->width = 3;
+ pccr->shift = QSGMII_CFG(A);
+ break;
+ case LANE_MODE_10G_QXGMII:
+ if (lane != 1)
+ return -EINVAL;
+
+ pccr->offset = PCCR9;
+ pccr->width = 3;
+ pccr->shift = QXGMII_CFG(A);
+ break;
+ case LANE_MODE_USXGMII:
+ if (lane != 0)
+ return -EINVAL;
+
+ pccr->offset = PCCRB;
+ pccr->width = 3;
+ pccr->shift = SXGMII_CFG(A);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int ls1028a_get_pcvt_offset(int lane, enum lynx_lane_mode mode)
+{
+ switch (mode) {
+ case LANE_MODE_1000BASEX_SGMII:
+ case LANE_MODE_2500BASEX:
+ return SGMIIaCR0(lane);
+ case LANE_MODE_QSGMII:
+ return lane == 1 ? QSGMIIaCR0(A) : -EINVAL;
+ case LANE_MODE_USXGMII:
+ return lane == 0 ? SXGMIIaCR0(A) : -EINVAL;
+ case LANE_MODE_10G_QXGMII:
+ return lane == 1 ? QXGMIIaCR0(A) : -EINVAL;
+ default:
+ return -EINVAL;
+ }
+}
+
+static const struct lynx_info lynx_info_ls1028a = {
+ .get_pccr = ls1028a_get_pccr,
+ .get_pcvt_offset = ls1028a_get_pcvt_offset,
+ .pll_read_configuration = lynx_10g_pll_read_configuration,
+ .lane_read_configuration = lynx_10g_lane_read_configuration,
+ .cdr_lock_check = lynx_10g_cdr_lock_check,
+ .num_lanes = 4,
+ .index = 1,
+ .quirks = LYNX_QUIRK_HAS_HARDCODED_USXGMII,
+};
+
+static int ls1046a_serdes1_get_pccr(enum lynx_lane_mode lane_mode, int lane,
+ struct lynx_pccr *pccr)
+{
+ switch (lane_mode) {
+ case LANE_MODE_1000BASEX_SGMII:
+ case LANE_MODE_2500BASEX:
+ pccr->offset = PCCR8;
+ pccr->width = 4;
+ pccr->shift = SGMII_CFG(lane);
+ break;
+ case LANE_MODE_QSGMII:
+ if (lane != 1)
+ return -EINVAL;
+
+ pccr->offset = PCCR9;
+ pccr->width = 3;
+ pccr->shift = QSGMII_CFG(B);
+ break;
+ case LANE_MODE_10GBASER:
+ switch (lane) {
+ case 2:
+ pccr->shift = XFI_CFG(A);
+ break;
+ case 3:
+ pccr->shift = XFI_CFG(B);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ pccr->offset = PCCRB;
+ pccr->width = 3;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int ls1046a_serdes1_get_pcvt_offset(int lane, enum lynx_lane_mode mode)
+{
+ switch (mode) {
+ case LANE_MODE_1000BASEX_SGMII:
+ case LANE_MODE_2500BASEX:
+ return SGMIIaCR0(lane);
+ case LANE_MODE_QSGMII:
+ if (lane != 1)
+ return -EINVAL;
+
+ return QSGMIIaCR0(B);
+ case LANE_MODE_10GBASER:
+ switch (lane) {
+ case 2:
+ return XFIaCR0(A);
+ case 3:
+ return XFIaCR0(B);
+ default:
+ return -EINVAL;
+ }
+ default:
+ return -EINVAL;
+ }
+}
+
+static const struct lynx_info lynx_info_ls1046a_serdes1 = {
+ .get_pccr = ls1046a_serdes1_get_pccr,
+ .get_pcvt_offset = ls1046a_serdes1_get_pcvt_offset,
+ .pll_read_configuration = lynx_10g_pll_read_configuration,
+ .lane_read_configuration = lynx_10g_lane_read_configuration,
+ .cdr_lock_check = lynx_10g_cdr_lock_check,
+ .num_lanes = 4,
+ .index = 1,
+};
+
+static int ls1046a_serdes2_get_pccr(enum lynx_lane_mode lane_mode, int lane,
+ struct lynx_pccr *pccr)
+{
+ switch (lane_mode) {
+ case LANE_MODE_1000BASEX_SGMII:
+ case LANE_MODE_2500BASEX:
+ if (lane != 1)
+ return -EINVAL;
+
+ pccr->offset = PCCR8;
+ pccr->width = 4;
+ pccr->shift = SGMII_CFG(B);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int ls1046a_serdes2_get_pcvt_offset(int lane, enum lynx_lane_mode mode)
+{
+ switch (mode) {
+ case LANE_MODE_1000BASEX_SGMII:
+ case LANE_MODE_2500BASEX:
+ if (lane != 1)
+ return -EINVAL;
+
+ return SGMIIaCR0(B);
+ default:
+ return -EINVAL;
+ }
+}
+
+static const struct lynx_info lynx_info_ls1046a_serdes2 = {
+ .get_pccr = ls1046a_serdes2_get_pccr,
+ .get_pcvt_offset = ls1046a_serdes2_get_pcvt_offset,
+ .pll_read_configuration = lynx_10g_pll_read_configuration,
+ .lane_read_configuration = lynx_10g_lane_read_configuration,
+ .cdr_lock_check = lynx_10g_cdr_lock_check,
+ .num_lanes = 4,
+ .index = 2,
+};
+
+static int ls1088a_serdes1_get_pccr(enum lynx_lane_mode lane_mode, int lane,
+ struct lynx_pccr *pccr)
+{
+ switch (lane_mode) {
+ case LANE_MODE_1000BASEX_SGMII:
+ pccr->offset = PCCR8;
+ pccr->width = 4;
+ pccr->shift = SGMII_CFG(lane);
+ break;
+ case LANE_MODE_QSGMII:
+ switch (lane) {
+ case 0:
+ pccr->shift = QSGMII_CFG(A);
+ break;
+ case 1:
+ case 3:
+ pccr->shift = QSGMII_CFG(B);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ pccr->offset = PCCR9;
+ pccr->width = 3;
+ break;
+ case LANE_MODE_10GBASER:
+ switch (lane) {
+ case 2:
+ pccr->shift = XFI_CFG(A);
+ break;
+ case 3:
+ pccr->shift = XFI_CFG(B);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ pccr->offset = PCCRB;
+ pccr->width = 3;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int ls1088a_serdes1_get_pcvt_offset(int lane, enum lynx_lane_mode mode)
+{
+ switch (mode) {
+ case LANE_MODE_1000BASEX_SGMII:
+ return SGMIIaCR0(lane);
+ case LANE_MODE_QSGMII:
+ switch (lane) {
+ case 0:
+ return QSGMIIaCR0(A);
+ case 1:
+ case 3:
+ return QSGMIIaCR0(B);
+ default:
+ return -EINVAL;
+ }
+ case LANE_MODE_10GBASER:
+ switch (lane) {
+ case 2:
+ return XFIaCR0(A);
+ case 3:
+ return XFIaCR0(B);
+ default:
+ return -EINVAL;
+ }
+ default:
+ return -EINVAL;
+ }
+}
+
+static const struct lynx_info lynx_info_ls1088a_serdes1 = {
+ .get_pccr = ls1088a_serdes1_get_pccr,
+ .get_pcvt_offset = ls1088a_serdes1_get_pcvt_offset,
+ .pll_read_configuration = lynx_10g_pll_read_configuration,
+ .lane_read_configuration = lynx_10g_lane_read_configuration,
+ .cdr_lock_check = lynx_10g_cdr_lock_check,
+ .num_lanes = 4,
+ .index = 1,
+};
+
+static int ls2088a_serdes1_get_pccr(enum lynx_lane_mode lane_mode, int lane,
+ struct lynx_pccr *pccr)
+{
+ switch (lane_mode) {
+ case LANE_MODE_1000BASEX_SGMII:
+ case LANE_MODE_2500BASEX:
+ pccr->offset = PCCR8;
+ pccr->width = 4;
+ pccr->shift = SGMII_CFG(lane);
+ break;
+ case LANE_MODE_QSGMII:
+ switch (lane) {
+ case 2:
+ case 6:
+ pccr->shift = QSGMII_CFG(A);
+ break;
+ case 7:
+ pccr->shift = QSGMII_CFG(B);
+ break;
+ case 0:
+ case 4:
+ pccr->shift = QSGMII_CFG(C);
+ break;
+ case 1:
+ case 5:
+ pccr->shift = QSGMII_CFG(D);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ pccr->offset = PCCR9;
+ pccr->width = 3;
+ break;
+ case LANE_MODE_10GBASER:
+ pccr->offset = PCCRB;
+ pccr->width = 3;
+ pccr->shift = XFI_CFG(lane);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int ls2088a_serdes1_get_pcvt_offset(int lane, enum lynx_lane_mode mode)
+{
+ switch (mode) {
+ case LANE_MODE_1000BASEX_SGMII:
+ case LANE_MODE_2500BASEX:
+ return SGMIIaCR0(lane);
+ case LANE_MODE_QSGMII:
+ switch (lane) {
+ case 2:
+ case 6:
+ return QSGMIIaCR0(A);
+ case 7:
+ return QSGMIIaCR0(B);
+ case 0:
+ case 4:
+ return QSGMIIaCR0(C);
+ case 1:
+ case 5:
+ return QSGMIIaCR0(D);
+ default:
+ return -EINVAL;
+ }
+ case LANE_MODE_10GBASER:
+ return XFIaCR0(lane);
+ default:
+ return -EINVAL;
+ }
+}
+
+static const struct lynx_info lynx_info_ls2088a_serdes1 = {
+ .get_pccr = ls2088a_serdes1_get_pccr,
+ .get_pcvt_offset = ls2088a_serdes1_get_pcvt_offset,
+ .pll_read_configuration = lynx_10g_pll_read_configuration,
+ .lane_read_configuration = lynx_10g_lane_read_configuration,
+ .cdr_lock_check = lynx_10g_cdr_lock_check,
+ .num_lanes = 8,
+ .index = 1,
+};
+
+static int ls2088a_serdes2_get_pccr(enum lynx_lane_mode lane_mode, int lane,
+ struct lynx_pccr *pccr)
+{
+ switch (lane_mode) {
+ case LANE_MODE_1000BASEX_SGMII:
+ case LANE_MODE_2500BASEX:
+ pccr->offset = PCCR8;
+ pccr->width = 4;
+ pccr->shift = SGMII_CFG(lane);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int ls2088a_serdes2_get_pcvt_offset(int lane, enum lynx_lane_mode mode)
+{
+ switch (mode) {
+ case LANE_MODE_1000BASEX_SGMII:
+ case LANE_MODE_2500BASEX:
+ return SGMIIaCR0(lane);
+ default:
+ return -EINVAL;
+ }
+}
+
+static const struct lynx_info lynx_info_ls2088a_serdes2 = {
+ .get_pccr = ls2088a_serdes2_get_pccr,
+ .get_pcvt_offset = ls2088a_serdes2_get_pcvt_offset,
+ .pll_read_configuration = lynx_10g_pll_read_configuration,
+ .lane_read_configuration = lynx_10g_lane_read_configuration,
+ .cdr_lock_check = lynx_10g_cdr_lock_check,
+ .num_lanes = 8,
+ .index = 2,
+};
+
+/* Halting puts the lane in a mode in which it can be reconfigured */
+static void lynx_10g_lane_halt(struct phy *phy)
+{
+ struct lynx_lane *lane = phy_get_drvdata(phy);
+
+ /* Issue a reset request */
+ lynx_lane_rmw(lane, LNaGCR0,
+ LNaGCR0_RRST_ON | LNaGCR0_TRST_ON,
+ LNaGCR0_RRST | LNaGCR0_TRST);
+
+ /* The RM says to wait for at least 50ns */
+ usleep_range(1, 2);
+}
+
+static void lynx_10g_lane_reset(struct phy *phy)
+{
+ struct lynx_lane *lane = phy_get_drvdata(phy);
+
+ /* Finalize the reset request */
+ lynx_lane_rmw(lane, LNaGCR0,
+ LNaGCR0_RRST_OFF | LNaGCR0_TRST_OFF,
+ LNaGCR0_RRST | LNaGCR0_TRST);
+}
+
+static int lynx_10g_power_off(struct phy *phy)
+{
+ struct lynx_lane *lane = phy_get_drvdata(phy);
+
+ if (!lane->powered_up)
+ return 0;
+
+ /* Issue a reset request with the power down bits set */
+ lynx_lane_rmw(lane, LNaGCR0,
+ LNaGCR0_RRST_ON | LNaGCR0_TRST_ON |
+ LNaGCR0_RX_PD | LNaGCR0_TX_PD,
+ LNaGCR0_RRST | LNaGCR0_TRST |
+ LNaGCR0_RX_PD | LNaGCR0_TX_PD);
+
+ /* The RM says to wait for at least 50ns */
+ usleep_range(1, 2);
+
+ lane->powered_up = false;
+
+ return 0;
+}
+
+static int lynx_10g_power_on(struct phy *phy)
+{
+ struct lynx_lane *lane = phy_get_drvdata(phy);
+
+ if (lane->powered_up)
+ return 0;
+
+ /* RM says that to enable a previously powered down lane, set
+ * LNmGCR0[{R,T}X_PD]=0, wait 15 us, then set LNmGCR0[{R,T}RST]=1.
+ */
+ lynx_lane_rmw(lane, LNaGCR0, 0, LNaGCR0_RX_PD | LNaGCR0_TX_PD);
+ usleep_range(150, 300);
+ lynx_10g_lane_reset(phy);
+
+ lane->powered_up = true;
+
+ return 0;
+}
+
+static void lynx_10g_lane_set_nrate(struct lynx_lane *lane,
+ struct lynx_pll *pll,
+ enum lynx_lane_mode mode)
+{
+ enum lynx_10g_rat_sel nrate;
+
+ switch (pll->frate_sel) {
+ case PLLnCR0_FRATE_5G:
+ switch (mode) {
+ case LANE_MODE_1000BASEX_SGMII:
+ nrate = RAT_SEL_QUARTER;
+ break;
+ case LANE_MODE_QSGMII:
+ nrate = RAT_SEL_FULL;
+ break;
+ default:
+ return;
+ }
+ break;
+ case PLLnCR0_FRATE_3_125G:
+ switch (mode) {
+ case LANE_MODE_2500BASEX:
+ nrate = RAT_SEL_FULL;
+ break;
+ default:
+ return;
+ }
+ break;
+ case PLLnCR0_FRATE_5_15625G:
+ switch (mode) {
+ case LANE_MODE_10GBASER:
+ case LANE_MODE_USXGMII:
+ case LANE_MODE_10G_QXGMII:
+ nrate = RAT_SEL_DOUBLE;
+ break;
+ default:
+ return;
+ }
+ break;
+ default:
+ return;
+ }
+
+ lynx_lane_rmw(lane, LNaGCR0,
+ FIELD_PREP(LNaGCR0_TRAT_SEL, nrate) |
+ FIELD_PREP(LNaGCR0_RRAT_SEL, nrate),
+ LNaGCR0_RRAT_SEL | LNaGCR0_TRAT_SEL);
+}
+
+static void lynx_10g_lane_set_pll(struct lynx_lane *lane,
+ struct lynx_pll *pll)
+{
+ if (pll->id == 0) {
+ lynx_lane_rmw(lane, LNaGCR0,
+ LNaGCR0_RPLL_PLLF | LNaGCR0_TPLL_PLLF,
+ LNaGCR0_RPLL_MSK | LNaGCR0_TPLL_MSK);
+ } else {
+ lynx_lane_rmw(lane, LNaGCR0,
+ LNaGCR0_RPLL_PLLS | LNaGCR0_TPLL_PLLS,
+ LNaGCR0_RPLL_MSK | LNaGCR0_TPLL_MSK);
+ }
+}
+
+static void lynx_10g_lane_remap_pll(struct lynx_lane *lane,
+ enum lynx_lane_mode lane_mode)
+{
+ struct lynx_priv *priv = lane->priv;
+ struct lynx_pll *pll;
+
+ /* Switch to the PLL that works with this interface type */
+ pll = lynx_pll_get(priv, lane_mode);
+ if (unlikely(!pll))
+ return;
+
+ lynx_10g_lane_set_pll(lane, pll);
+
+ /* Choose the portion of clock net to be used on this lane */
+ lynx_10g_lane_set_nrate(lane, pll, lane_mode);
+}
+
+static void lynx_10g_lane_change_proto_conf(struct lynx_lane *lane,
+ enum lynx_lane_mode mode)
+{
+ const struct lynx_10g_proto_conf *conf = &lynx_10g_proto_conf[mode];
+
+ lynx_lane_rmw(lane, LNaGCR0,
+ FIELD_PREP(LNaGCR0_PROTS, conf->proto_sel) |
+ FIELD_PREP(LNaGCR0_IF20BIT_EN, conf->if20bit_en),
+ LNaGCR0_PROTS | LNaGCR0_IF20BIT_EN);
+ lynx_lane_rmw(lane, LNaGCR1,
+ FIELD_PREP(LNaGCR1_REIDL_TH, conf->reidl_th) |
+ FIELD_PREP(LNaGCR1_REIDL_ET_MSB, conf->reidl_et_msb) |
+ FIELD_PREP(LNaGCR1_REIDL_ET_SEL, conf->reidl_et_sel) |
+ FIELD_PREP(LNaGCR1_REIDL_EX_MSB, conf->reidl_ex_msb) |
+ FIELD_PREP(LNaGCR1_REIDL_EX_SEL, conf->reidl_ex_sel) |
+ FIELD_PREP(LNaGCR1_ISLEW_RCTL, conf->islew_rctl) |
+ FIELD_PREP(LNaGCR1_OSLEW_RCTL, conf->oslew_rctl),
+ LNaGCR1_REIDL_TH |
+ LNaGCR1_REIDL_ET_MSB | LNaGCR1_REIDL_ET_SEL |
+ LNaGCR1_REIDL_EX_MSB | LNaGCR1_REIDL_EX_SEL |
+ LNaGCR1_ISLEW_RCTL | LNaGCR1_OSLEW_RCTL);
+ lynx_lane_rmw(lane, LNaRECR0,
+ FIELD_PREP(LNaRECR0_RXEQ_BST, conf->rxeq_bst) |
+ FIELD_PREP(LNaRECR0_GK2OVD, conf->gk2ovd) |
+ FIELD_PREP(LNaRECR0_GK3OVD, conf->gk3ovd) |
+ FIELD_PREP(LNaRECR0_GK2OVD_EN, conf->gk2ovd_en) |
+ FIELD_PREP(LNaRECR0_GK3OVD_EN, conf->gk3ovd_en) |
+ FIELD_PREP(LNaRECR0_BASE_WAND, conf->base_wand),
+ LNaRECR0_RXEQ_BST | LNaRECR0_GK2OVD | LNaRECR0_GK3OVD |
+ LNaRECR0_GK2OVD_EN | LNaRECR0_GK3OVD_EN |
+ LNaRECR0_BASE_WAND);
+ lynx_lane_rmw(lane, LNaTECR0,
+ FIELD_PREP(LNaTECR0_TEQ_TYPE, conf->teq_type) |
+ FIELD_PREP(LNaTECR0_SGN_PREQ, conf->sgn_preq) |
+ FIELD_PREP(LNaTECR0_RATIO_PREQ, conf->ratio_preq) |
+ FIELD_PREP(LNaTECR0_SGN_POST1Q, conf->sgn_post1q) |
+ FIELD_PREP(LNaTECR0_RATIO_PST1Q, conf->ratio_post1q) |
+ FIELD_PREP(LNaTECR0_ADPT_EQ, conf->adpt_eq) |
+ FIELD_PREP(LNaTECR0_AMP_RED, conf->amp_red),
+ LNaTECR0_TEQ_TYPE | LNaTECR0_SGN_PREQ |
+ LNaTECR0_RATIO_PREQ | LNaTECR0_SGN_POST1Q |
+ LNaTECR0_RATIO_PST1Q | LNaTECR0_ADPT_EQ |
+ LNaTECR0_AMP_RED);
+ lynx_lane_write(lane, LNaTTLCR0, conf->ttlcr0);
+}
+
+static int lynx_10g_lane_disable_pcvt(struct lynx_lane *lane,
+ enum lynx_lane_mode mode)
+{
+ struct lynx_priv *priv = lane->priv;
+ int err;
+
+ spin_lock(&priv->pcc_lock);
+
+ err = lynx_pccr_write(lane, mode, 0);
+ if (err)
+ goto out;
+
+ switch (mode) {
+ case LANE_MODE_1000BASEX_SGMII:
+ case LANE_MODE_2500BASEX:
+ err = lynx_pcvt_rmw(lane, mode, CR(1), SGMIIaCR1_SGPCS_DIS,
+ SGMIIaCR1_SGPCS_EN);
+ if (err)
+ goto out;
+
+ lynx_pcvt_rmw(lane, mode, CR(0),
+ SGMIIaCR0_RST_SGM_ON | SGMIIaCR0_PD_SGM,
+ SGMIIaCR0_RST_SGM | SGMIIaCR0_PD_SGM);
+ break;
+ case LANE_MODE_QSGMII:
+ err = lynx_pcvt_rmw(lane, mode, CR(0),
+ QSGMIIaCR0_RST_QSGM_ON | QSGMIIaCR0_PD_QSGM,
+ QSGMIIaCR0_RST_QSGM | QSGMIIaCR0_PD_QSGM);
+ if (err)
+ goto out;
+ break;
+ default:
+ err = 0;
+ }
+
+out:
+ spin_unlock(&priv->pcc_lock);
+
+ return err;
+}
+
+static int lynx_10g_lane_enable_pcvt(struct lynx_lane *lane,
+ enum lynx_lane_mode mode)
+{
+ struct lynx_priv *priv = lane->priv;
+ u32 val;
+ int err;
+
+ spin_lock(&priv->pcc_lock);
+
+ switch (mode) {
+ case LANE_MODE_1000BASEX_SGMII:
+ case LANE_MODE_2500BASEX:
+ err = lynx_pcvt_rmw(lane, mode, CR(1), SGMIIaCR1_SGPCS_EN,
+ SGMIIaCR1_SGPCS_EN);
+ if (err)
+ goto out;
+
+ lynx_pcvt_rmw(lane, mode, CR(0), SGMIIaCR0_RST_SGM_OFF,
+ SGMIIaCR0_RST_SGM | SGMIIaCR0_PD_SGM);
+ break;
+ case LANE_MODE_QSGMII:
+ err = lynx_pcvt_rmw(lane, mode, CR(0), QSGMIIaCR0_RST_QSGM_OFF,
+ QSGMIIaCR0_RST_QSGM | QSGMIIaCR0_PD_QSGM);
+ if (err)
+ goto out;
+ break;
+ default:
+ err = 0;
+ }
+
+ if (lane->default_pccr[mode]) {
+ err = lynx_pccr_write(lane, mode, lane->default_pccr[mode]);
+ goto out;
+ }
+
+ val = 0;
+
+ switch (mode) {
+ case LANE_MODE_1000BASEX_SGMII:
+ case LANE_MODE_2500BASEX:
+ val |= PCCR8_SGMIIa_CFG;
+ break;
+ case LANE_MODE_QSGMII:
+ val |= PCCR9_QSGMIIa_CFG;
+ break;
+ case LANE_MODE_10G_QXGMII:
+ val |= PCCR9_QXGMIIa_CFG;
+ break;
+ case LANE_MODE_10GBASER:
+ val |= PCCRB_XFIa_CFG;
+ break;
+ case LANE_MODE_USXGMII:
+ val |= PCCRB_SXGMIIa_CFG;
+ break;
+ default:
+ err = 0;
+ goto out;
+ }
+
+ err = lynx_pccr_write(lane, mode, val);
+out:
+ spin_unlock(&priv->pcc_lock);
+
+ return err;
+}
+
+static bool lynx_10g_lane_mode_needs_rcw_override(struct lynx_lane *lane,
+ enum lynx_lane_mode new)
+{
+ enum lynx_lane_mode curr = lane->mode;
+
+ /* Major protocol changes, which involve changing the PCS connection to
+ * the GMII MAC with the one to the XGMII MAC, require an RCW override
+ * procedure to reconfigure an internal mux, as documented here:
+ * https://lore.kernel.org/linux-phy/20230810102631.bvozjer3t67r67iy@skbuf/
+ * This is SoC-specific, and not yet implemented in drivers/soc/fsl/guts.c.
+ *
+ * So the supported set of protocols depends on the initial lane mode.
+ *
+ * Minor protocol changes (SGMII <-> 1000Base-X <-> 2500Base-X or
+ * 10GBase-R <-> USXGMII) are supported.
+ */
+ if ((lynx_lane_mode_uses_gmii_mac(curr) &&
+ lynx_lane_mode_uses_xgmii_mac(new)) ||
+ (lynx_lane_mode_uses_xgmii_mac(curr) &&
+ lynx_lane_mode_uses_gmii_mac(new)))
+ return true;
+
+ return false;
+}
+
+static int lynx_10g_validate(struct phy *phy, enum phy_mode mode, int submode,
+ union phy_configure_opts *opts)
+{
+ struct lynx_lane *lane = phy_get_drvdata(phy);
+ enum lynx_lane_mode lane_mode;
+ int err;
+
+ err = lynx_phy_mode_to_lane_mode(phy, mode, submode, &lane_mode);
+ if (err)
+ return err;
+
+ if (lynx_10g_lane_mode_needs_rcw_override(lane, lane_mode))
+ return -EINVAL;
+
+ return 0;
+}
+
+static int lynx_10g_set_mode(struct phy *phy, enum phy_mode mode, int submode)
+{
+ struct lynx_lane *lane = phy_get_drvdata(phy);
+ bool powered_up = lane->powered_up;
+ enum lynx_lane_mode lane_mode;
+ int err;
+
+ err = lynx_10g_validate(phy, mode, submode, NULL);
+ if (err)
+ return err;
+
+ lane_mode = phy_interface_to_lane_mode(submode);
+ /* lynx_10g_validate() already made sure the lane_mode is supported */
+
+ if (lane_mode == lane->mode)
+ return 0;
+
+ /* If the lane is powered up, put the lane into the halt state while
+ * the reconfiguration is being done.
+ */
+ if (powered_up)
+ lynx_10g_lane_halt(phy);
+
+ err = lynx_10g_lane_disable_pcvt(lane, lane->mode);
+ if (err)
+ goto out;
+
+ lynx_10g_lane_change_proto_conf(lane, lane_mode);
+ lynx_10g_lane_remap_pll(lane, lane_mode);
+ WARN_ON(lynx_10g_lane_enable_pcvt(lane, lane_mode));
+
+ lane->mode = lane_mode;
+
+out:
+ if (powered_up) {
+ /* The RM says to wait for at least 120 ns */
+ usleep_range(1, 2);
+ lynx_10g_lane_reset(phy);
+ }
+
+ return err;
+}
+
+static int lynx_10g_init(struct phy *phy)
+{
+ struct lynx_lane *lane = phy_get_drvdata(phy);
+
+ /* Mark the fact that the lane was init */
+ lane->init = true;
+
+ /* SerDes lanes are powered on at boot time. Any lane that is
+ * managed by this driver will get powered off when its consumer
+ * calls phy_init().
+ */
+ lane->powered_up = true;
+ lynx_10g_power_off(phy);
+
+ return 0;
+}
+
+static int lynx_10g_exit(struct phy *phy)
+{
+ struct lynx_lane *lane = phy_get_drvdata(phy);
+
+ /* The lane returns to the state where it isn't managed by the
+ * consumer, so we must treat is as if it isn't initialized, and always
+ * powered on.
+ */
+ lane->init = false;
+ lane->powered_up = false;
+ lynx_10g_power_on(phy);
+
+ return 0;
+}
+
+static const struct phy_ops lynx_10g_ops = {
+ .init = lynx_10g_init,
+ .exit = lynx_10g_exit,
+ .power_on = lynx_10g_power_on,
+ .power_off = lynx_10g_power_off,
+ .set_mode = lynx_10g_set_mode,
+ .validate = lynx_10g_validate,
+ .owner = THIS_MODULE,
+};
+
+static int lynx_10g_probe(struct platform_device *pdev)
+{
+ return lynx_probe(pdev, of_device_get_match_data(&pdev->dev),
+ &lynx_10g_ops);
+}
+
+static const struct of_device_id lynx_10g_of_match_table[] = {
+ { .compatible = "fsl,ls1028a-serdes", .data = &lynx_info_ls1028a },
+ { .compatible = "fsl,ls1046a-serdes1", .data = &lynx_info_ls1046a_serdes1 },
+ { .compatible = "fsl,ls1046a-serdes2", .data = &lynx_info_ls1046a_serdes2 },
+ { .compatible = "fsl,ls1088a-serdes1", .data = &lynx_info_ls1088a_serdes1 },
+ { .compatible = "fsl,ls2088a-serdes1", .data = &lynx_info_ls2088a_serdes1 },
+ { .compatible = "fsl,ls2088a-serdes2", .data = &lynx_info_ls2088a_serdes2 },
+ {}
+};
+MODULE_DEVICE_TABLE(of, lynx_10g_of_match_table);
+
+static struct platform_driver lynx_10g_driver = {
+ .probe = lynx_10g_probe,
+ .remove = lynx_remove,
+ .driver = {
+ .name = "lynx-10g",
+ .of_match_table = lynx_10g_of_match_table,
+ },
+};
+module_platform_driver(lynx_10g_driver);
+
+MODULE_IMPORT_NS("PHY_FSL_LYNX");
+MODULE_AUTHOR("Ioana Ciornei <ioana.ciornei@nxp.com>");
+MODULE_AUTHOR("Vladimir Oltean <vladimir.oltean@nxp.com>");
+MODULE_DESCRIPTION("Lynx 10G SerDes PHY driver for Layerscape SoCs");
+MODULE_LICENSE("GPL");
diff --git a/drivers/phy/freescale/phy-fsl-lynx-core.c b/drivers/phy/freescale/phy-fsl-lynx-core.c
index 1e411bfab404..2cfe9236ffc5 100644
--- a/drivers/phy/freescale/phy-fsl-lynx-core.c
+++ b/drivers/phy/freescale/phy-fsl-lynx-core.c
@@ -11,6 +11,12 @@ const char *lynx_lane_mode_str(enum lynx_lane_mode lane_mode)
switch (lane_mode) {
case LANE_MODE_1000BASEX_SGMII:
return "1000Base-X/SGMII";
+ case LANE_MODE_2500BASEX:
+ return "2500Base-X";
+ case LANE_MODE_QSGMII:
+ return "QSGMII";
+ case LANE_MODE_10G_QXGMII:
+ return "10G-QXGMII";
case LANE_MODE_10GBASER:
return "10GBase-R";
case LANE_MODE_USXGMII:
@@ -29,6 +35,12 @@ enum lynx_lane_mode phy_interface_to_lane_mode(phy_interface_t intf)
case PHY_INTERFACE_MODE_SGMII:
case PHY_INTERFACE_MODE_1000BASEX:
return LANE_MODE_1000BASEX_SGMII;
+ case PHY_INTERFACE_MODE_2500BASEX:
+ return LANE_MODE_2500BASEX;
+ case PHY_INTERFACE_MODE_QSGMII:
+ return LANE_MODE_QSGMII;
+ case PHY_INTERFACE_MODE_10G_QXGMII:
+ return LANE_MODE_10G_QXGMII;
case PHY_INTERFACE_MODE_10GBASER:
return LANE_MODE_10GBASER;
case PHY_INTERFACE_MODE_USXGMII:
@@ -89,6 +101,29 @@ bool lynx_lane_supports_mode(struct lynx_lane *lane, enum lynx_lane_mode mode)
}
EXPORT_SYMBOL_NS_GPL(lynx_lane_supports_mode, "PHY_FSL_LYNX");
+/* The quad protocols are fixed because the lane has multiple consumers, and
+ * one phy_set_mode_ext() affects the other consumers as well. We have no use
+ * case for dynamic protocol changing here, so disallow it.
+ */
+static enum lynx_lane_mode lynx_fixed_protocols[] = {
+ LANE_MODE_QSGMII,
+ LANE_MODE_10G_QXGMII,
+};
+
+static bool lynx_lane_restrict_fixed_mode_change(struct lynx_lane *lane,
+ enum lynx_lane_mode new)
+{
+ enum lynx_lane_mode curr = lane->mode;
+
+ for (int i = 0; i < ARRAY_SIZE(lynx_fixed_protocols); i++)
+ if ((curr == lynx_fixed_protocols[i] ||
+ new == lynx_fixed_protocols[i]) &&
+ curr != new)
+ return true;
+
+ return false;
+}
+
/* Translate the mode/submode from phy_validate() and phy_set_mode_ext() to a
* lane_mode and return 0 if it is supported and we can transition to it from
* the current lane mode, or return negative error otherwise.
@@ -112,6 +147,9 @@ int lynx_phy_mode_to_lane_mode(struct phy *phy, enum phy_mode mode,
if (!lynx_lane_supports_mode(lane, tmp_lane_mode))
return -EINVAL;
+ if (lynx_lane_restrict_fixed_mode_change(lane, tmp_lane_mode))
+ return -EINVAL;
+
if (lane_mode)
*lane_mode = tmp_lane_mode;
diff --git a/drivers/phy/freescale/phy-fsl-lynx-core.h b/drivers/phy/freescale/phy-fsl-lynx-core.h
index 37fa4b544faa..a60429ba9324 100644
--- a/drivers/phy/freescale/phy-fsl-lynx-core.h
+++ b/drivers/phy/freescale/phy-fsl-lynx-core.h
@@ -9,6 +9,7 @@
#include <soc/fsl/phy-fsl-lynx.h>
#define LYNX_NUM_PLL 2
+#define LYNX_QUIRK_HAS_HARDCODED_USXGMII BIT(0)
struct lynx_priv;
struct lynx_lane;
@@ -36,6 +37,7 @@ struct lynx_lane {
bool init;
unsigned int id;
enum lynx_lane_mode mode;
+ u32 default_pccr[LANE_MODE_MAX];
};
struct lynx_info {
@@ -48,6 +50,8 @@ struct lynx_info {
void (*cdr_lock_check)(struct lynx_lane *lane);
int first_lane;
int num_lanes;
+ int index;
+ unsigned long quirks;
};
struct lynx_priv {
diff --git a/include/soc/fsl/phy-fsl-lynx.h b/include/soc/fsl/phy-fsl-lynx.h
index 92e8272d5ae1..ff5a7d1835b5 100644
--- a/include/soc/fsl/phy-fsl-lynx.h
+++ b/include/soc/fsl/phy-fsl-lynx.h
@@ -7,10 +7,37 @@
enum lynx_lane_mode {
LANE_MODE_UNKNOWN,
LANE_MODE_1000BASEX_SGMII,
+ LANE_MODE_2500BASEX,
+ LANE_MODE_QSGMII,
+ LANE_MODE_10G_QXGMII,
LANE_MODE_10GBASER,
LANE_MODE_USXGMII,
LANE_MODE_25GBASER,
LANE_MODE_MAX,
};
+static inline bool lynx_lane_mode_uses_gmii_mac(enum lynx_lane_mode mode)
+{
+ switch (mode) {
+ case LANE_MODE_1000BASEX_SGMII:
+ case LANE_MODE_2500BASEX:
+ case LANE_MODE_QSGMII:
+ case LANE_MODE_10G_QXGMII:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static inline bool lynx_lane_mode_uses_xgmii_mac(enum lynx_lane_mode mode)
+{
+ switch (mode) {
+ case LANE_MODE_10GBASER:
+ case LANE_MODE_USXGMII:
+ return true;
+ default:
+ return false;
+ }
+}
+
#endif /* __PHY_FSL_LYNX_H_ */
--
2.34.1
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox