* [PATCH v2 0/3] Add Loongson-2K0300 APB DMA mux support
@ 2026-10-09 9:19 Binbin Zhou
2026-10-09 9:19 ` [PATCH v2 1/3] dt-bindings: dma: loongson: Add Loongson-2 DMA mux request IDs Binbin Zhou
` (2 more replies)
0 siblings, 3 replies; 6+ messages in thread
From: Binbin Zhou @ 2026-10-09 9:19 UTC (permalink / raw)
To: Binbin Zhou, Huacai Chen, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Vinod Koul, Frank Li, dmaengine
Cc: Huacai Chen, Xuerui Wang, loongarch, devicetree, Keguang Zhang,
Binbin Zhou
Hi all:
Loongson-2K0300 integrates a CMC DMA controller with 8 physical
channels. Peripheral DMA requests are not hard-wired to these channels;
they are routed through the CHIP_CTRL13/14/15 DMA_MAP fields.
This series adds support for that DMA request router.
Patch 1 adds the DT binding constants for the peripheral request IDs.
Patch 2 adds the DT binding documentation for the DMA mux.
Patch 3 adds the driver, Kconfig symbol and Makefile entry.
The driver registers with of_dma_router_register(). In the route
allocation callback it validates the <request> <channel> <flags>
specifier, programs the SoC-specific route register, and forwards
<channel> <flags> to the parent CMC DMA controller.
Thanks.
Binbin.
=========
V2:
Patch(1/3):
- Drop LS2K0300_DMA_REQ_MAX as it is not part of the ABI;
Patch(2/3):
- More detailed description of `dma-cells`;
- Add the `dma_requests` constraint
Patch(3/3):
- Drop loongson2_dmamux_map->shift;
- Move of_parse_phandle() into loongson2_dmamux_route_allocate() avoid
UAF;
- Drop loongson2_dmamux->dma_np;
- Check dma_requests;
- Add devm_add_action_or_reset() instead of .remove();
- Replace `metux()` with `spinlock()`, which has lower overhead;
- Add loongson2_dmamux_route_free().
Link to V1:
https://lore.kernel.org/all/cover.1790068409.git.zhoubinbin@loongson.cn/
Binbin Zhou (3):
dt-bindings: dma: loongson: Add Loongson-2 DMA mux request IDs
dt-bindings: dma: loongson: Add Loongson-2K0300 DMA mux support
dmaengine: loongson: Add Loongson-2K0300 APB DMA mux driver
.../dma/loongson,ls2k0300-dmamux.yaml | 72 ++++
MAINTAINERS | 3 +
drivers/dma/loongson/Makefile | 1 +
drivers/dma/loongson/loongson2-apb-dmamux.c | 398 ++++++++++++++++++
.../dt-bindings/dma/loongson,ls2k-dmamux.h | 53 +++
5 files changed, 527 insertions(+)
create mode 100644 Documentation/devicetree/bindings/dma/loongson,ls2k0300-dmamux.yaml
create mode 100644 drivers/dma/loongson/loongson2-apb-dmamux.c
create mode 100644 include/dt-bindings/dma/loongson,ls2k-dmamux.h
base-commit: 1d8ae2003de08f61095e4e928b1b8cce6c23cabd
--
2.52.0
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH v2 1/3] dt-bindings: dma: loongson: Add Loongson-2 DMA mux request IDs
2026-10-09 9:19 [PATCH v2 0/3] Add Loongson-2K0300 APB DMA mux support Binbin Zhou
@ 2026-10-09 9:19 ` Binbin Zhou
2026-10-09 14:38 ` Conor Dooley
2026-10-09 9:19 ` [PATCH v2 2/3] dt-bindings: dma: loongson: Add Loongson-2K0300 DMA mux support Binbin Zhou
2026-10-09 9:19 ` [PATCH v2 3/3] dmaengine: loongson: Add Loongson-2K0300 APB DMA mux driver Binbin Zhou
2 siblings, 1 reply; 6+ messages in thread
From: Binbin Zhou @ 2026-10-09 9:19 UTC (permalink / raw)
To: Binbin Zhou, Huacai Chen, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Vinod Koul, Frank Li, dmaengine
Cc: Huacai Chen, Xuerui Wang, loongarch, devicetree, Keguang Zhang,
Binbin Zhou
Add DT binding constants for the Loongson-2 DMA mux.
The header defines the peripheral request IDs used in the DMA specifier
<request channel flags> for Loongson-2K0300, covering UART0-9, I2C0-3,
SPI2/3, I2S, ADC and CAN0-3. It also documents the channel-pair semantics
for peripherals that use paired DMA channels.
Signed-off-by: Binbin Zhou <zhoubinbin@loongson.cn>
---
MAINTAINERS | 1 +
.../dt-bindings/dma/loongson,ls2k-dmamux.h | 53 +++++++++++++++++++
2 files changed, 54 insertions(+)
create mode 100644 include/dt-bindings/dma/loongson,ls2k-dmamux.h
diff --git a/MAINTAINERS b/MAINTAINERS
index 42f5165019ee..172dde21275f 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -15354,6 +15354,7 @@ F: Documentation/devicetree/bindings/dma/loongson,ls2k0300-dma.yaml
F: Documentation/devicetree/bindings/dma/loongson,ls2x-apbdma.yaml
F: drivers/dma/loongson/loongson2-apb-cmc-dma.c
F: drivers/dma/loongson/loongson2-apb-dma.c
+F: include/dt-bindings/dma/loongson,ls2k-dmamux.h
LOONGSON LS2X I2C DRIVER
M: Binbin Zhou <zhoubinbin@loongson.cn>
diff --git a/include/dt-bindings/dma/loongson,ls2k-dmamux.h b/include/dt-bindings/dma/loongson,ls2k-dmamux.h
new file mode 100644
index 000000000000..1e2907ab069d
--- /dev/null
+++ b/include/dt-bindings/dma/loongson,ls2k-dmamux.h
@@ -0,0 +1,53 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
+/*
+ * Loongson-2 SoC DMA Mux dt-bindings
+ *
+ * DMA specifier format:
+ * dmas = <&dma_mux <request> <channel> <flags>>;
+ *
+ * The <channel> cell selects a physical CMC DMA channel (0-7)
+ * For peripherals using channel pairs (UART, I2C, SPI2/3, I2S),
+ * the channel number selects the pair: 0/1 -> pair 0, 2/3 -> pair 1,
+ * 4/5 -> pair 2, 6/7 -> pair 3.
+ *
+ * Copyright (C) 2026 Loongson Technology Corporation Limited
+ */
+
+#ifndef _DT_BINDINGS_DMA_LOONGSON_LS2K_DMAMUX_H
+#define _DT_BINDINGS_DMA_LOONGSON_LS2K_DMAMUX_H
+
+/* UART controllers */
+#define LS2K0300_DMA_UART0 0
+#define LS2K0300_DMA_UART1 1
+#define LS2K0300_DMA_UART2 2
+#define LS2K0300_DMA_UART3 3
+#define LS2K0300_DMA_UART4 4
+#define LS2K0300_DMA_UART5 5
+#define LS2K0300_DMA_UART6 6
+#define LS2K0300_DMA_UART7 7
+#define LS2K0300_DMA_UART8 8
+#define LS2K0300_DMA_UART9 9
+
+/* I2C controllers */
+#define LS2K0300_DMA_I2C0 10
+#define LS2K0300_DMA_I2C1 11
+#define LS2K0300_DMA_I2C2 12
+#define LS2K0300_DMA_I2C3 13
+
+/* SPI controllers (IO mode) */
+#define LS2K0300_DMA_SPI2 14
+#define LS2K0300_DMA_SPI3 15
+
+/* I2S controller */
+#define LS2K0300_DMA_I2S 16
+
+/* ADC controller */
+#define LS2K0300_DMA_ADC 17
+
+/* CAN-FD controllers */
+#define LS2K0300_DMA_CAN0 18
+#define LS2K0300_DMA_CAN1 19
+#define LS2K0300_DMA_CAN2 20
+#define LS2K0300_DMA_CAN3 21
+
+#endif /* _DT_BINDINGS_DMA_LOONGSON_LS2K_DMAMUX_H */
--
2.52.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH v2 2/3] dt-bindings: dma: loongson: Add Loongson-2K0300 DMA mux support
2026-10-09 9:19 [PATCH v2 0/3] Add Loongson-2K0300 APB DMA mux support Binbin Zhou
2026-10-09 9:19 ` [PATCH v2 1/3] dt-bindings: dma: loongson: Add Loongson-2 DMA mux request IDs Binbin Zhou
@ 2026-10-09 9:19 ` Binbin Zhou
2026-10-09 14:43 ` Conor Dooley
2026-10-09 9:19 ` [PATCH v2 3/3] dmaengine: loongson: Add Loongson-2K0300 APB DMA mux driver Binbin Zhou
2 siblings, 1 reply; 6+ messages in thread
From: Binbin Zhou @ 2026-10-09 9:19 UTC (permalink / raw)
To: Binbin Zhou, Huacai Chen, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Vinod Koul, Frank Li, dmaengine
Cc: Huacai Chen, Xuerui Wang, loongarch, devicetree, Keguang Zhang,
Binbin Zhou
The DMA mux on Loongson-2K0300 is not a standalone hardware block. It is
implemented as part of the chip configuration registers CHIP_CTRL13/14/15,
which route peripheral DMA requests to the physical channels of the CMC
DMA controller.
Document this as a DMA router. The #dma-cells = <3> specifier contains
the peripheral request ID, the target CMC DMA channel, and channel
configuration flags forwarded to the parent DMA controller.
Signed-off-by: Binbin Zhou <zhoubinbin@loongson.cn>
---
.../dma/loongson,ls2k0300-dmamux.yaml | 72 +++++++++++++++++++
MAINTAINERS | 1 +
2 files changed, 73 insertions(+)
create mode 100644 Documentation/devicetree/bindings/dma/loongson,ls2k0300-dmamux.yaml
diff --git a/Documentation/devicetree/bindings/dma/loongson,ls2k0300-dmamux.yaml b/Documentation/devicetree/bindings/dma/loongson,ls2k0300-dmamux.yaml
new file mode 100644
index 000000000000..0e6c794e1c90
--- /dev/null
+++ b/Documentation/devicetree/bindings/dma/loongson,ls2k0300-dmamux.yaml
@@ -0,0 +1,72 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/dma/loongson,ls2k0300-dmamux.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Loongson-2 APB DMA MUX (DMA request router)
+
+maintainers:
+ - Binbin Zhou <zhoubinbin@loongson.cn>
+
+allOf:
+ - $ref: /schemas/dma/dma-router.yaml#
+
+properties:
+ compatible:
+ const: loongson,ls2k0300-dmamux
+
+ reg:
+ maxItems: 1
+
+ '#dma-cells':
+ const: 3
+ description: |
+ Each cell represents the following:
+ 1. Peripheral request ID: This describes the corresponding bit field
+ for that peripheral in the configuration register; see (
+ include/dt-bindings/dma/loongson,ls2k-dmamux.h) for details.
+ 2. Physical DMA channel (0-7): This not only represents the DMA
+ channel used by the peripheral but is also converted into a value for
+ the corresponding bit field in the configuration register, indicating
+ the legitimacy of that peripheral using that channel.
+ Specifically:
+ - I2S/SPI/UART/I2C: Require adjacent channels in pairs; valid
+ values are 0/1, 2/3, 4/5, 6/7;
+ - SM3/SM4/DES/AES: Single channel; valid values are limited to 0/1;
+ - CAN/ADC: Single channel; valid values range from 0 to 7.
+ 3. DMA Channel Configuration: A 32-bit mask used to specify
+ device-specific DMA channel configurations.
+ - Bit 6: Peripheral Address Increment Mode
+ 0x0: Disabled
+ 0x1: Enabled
+ - Bit 7: Memory Address Increment Mode
+ 0x0: Disabled
+ 0x1: Enabled
+ - Bits 12-13: Priority
+ 0x0: Low
+ 0x1: Medium
+ 0x2: High
+ 0x3: Very High
+
+ dma-requests:
+ const: 22
+
+required:
+ - compatible
+ - reg
+ - dma-requests
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/dma/loongson,ls2k-dmamux.h>
+ dma-router@16000134 {
+ compatible = "loongson,ls2k0300-dmamux";
+ reg = <0x16000134 0xc>;
+ #dma-cells = <3>;
+ dma-masters = <&dma>;
+ dma-requests = <22>;
+ };
+...
diff --git a/MAINTAINERS b/MAINTAINERS
index 172dde21275f..78622b255f88 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -15351,6 +15351,7 @@ M: Binbin Zhou <zhoubinbin@loongson.cn>
L: dmaengine@vger.kernel.org
S: Maintained
F: Documentation/devicetree/bindings/dma/loongson,ls2k0300-dma.yaml
+F: Documentation/devicetree/bindings/dma/loongson,ls2k0300-dmamux.yaml
F: Documentation/devicetree/bindings/dma/loongson,ls2x-apbdma.yaml
F: drivers/dma/loongson/loongson2-apb-cmc-dma.c
F: drivers/dma/loongson/loongson2-apb-dma.c
--
2.52.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH v2 3/3] dmaengine: loongson: Add Loongson-2K0300 APB DMA mux driver
2026-10-09 9:19 [PATCH v2 0/3] Add Loongson-2K0300 APB DMA mux support Binbin Zhou
2026-10-09 9:19 ` [PATCH v2 1/3] dt-bindings: dma: loongson: Add Loongson-2 DMA mux request IDs Binbin Zhou
2026-10-09 9:19 ` [PATCH v2 2/3] dt-bindings: dma: loongson: Add Loongson-2K0300 DMA mux support Binbin Zhou
@ 2026-10-09 9:19 ` Binbin Zhou
2 siblings, 0 replies; 6+ messages in thread
From: Binbin Zhou @ 2026-10-09 9:19 UTC (permalink / raw)
To: Binbin Zhou, Huacai Chen, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Vinod Koul, Frank Li, dmaengine
Cc: Huacai Chen, Xuerui Wang, loongarch, devicetree, Keguang Zhang,
Binbin Zhou
The Loongson-2K0300 DMA mux is not a standalone DMA controller. It is
implemented as a set of routing fields in the chip global configuration
registers CHIP_CTRL13/14/15, which select which physical channel of the
on-chip CMC DMA controller handles each peripheral DMA request.
Add a driver that exposes these routing fields as an OF DMA router. The
router's allocation callback validates the <request> <channel> <flags>
specifier, programs the corresponding CHIP_CTRL register field, and then
rewrites the specifier to <channel> <flags> so that the parent CMC DMA
controller's xlate is used.
Signed-off-by: Binbin Zhou <zhoubinbin@loongson.cn>
---
MAINTAINERS | 1 +
drivers/dma/loongson/Makefile | 1 +
drivers/dma/loongson/loongson2-apb-dmamux.c | 398 ++++++++++++++++++++
3 files changed, 400 insertions(+)
create mode 100644 drivers/dma/loongson/loongson2-apb-dmamux.c
diff --git a/MAINTAINERS b/MAINTAINERS
index 78622b255f88..0b0c6ea41c64 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -15355,6 +15355,7 @@ F: Documentation/devicetree/bindings/dma/loongson,ls2k0300-dmamux.yaml
F: Documentation/devicetree/bindings/dma/loongson,ls2x-apbdma.yaml
F: drivers/dma/loongson/loongson2-apb-cmc-dma.c
F: drivers/dma/loongson/loongson2-apb-dma.c
+F: drivers/dma/loongson/loongson2-apb-dmamux.c
F: include/dt-bindings/dma/loongson,ls2k-dmamux.h
LOONGSON LS2X I2C DRIVER
diff --git a/drivers/dma/loongson/Makefile b/drivers/dma/loongson/Makefile
index 48c19781e729..271fd38fa8f2 100644
--- a/drivers/dma/loongson/Makefile
+++ b/drivers/dma/loongson/Makefile
@@ -2,3 +2,4 @@
obj-$(CONFIG_LOONGSON1_APB_DMA) += loongson1-apb-dma.o
obj-$(CONFIG_LOONGSON2_APB_DMA) += loongson2-apb-dma.o
obj-$(CONFIG_LOONGSON2_APB_CMC_DMA) += loongson2-apb-cmc-dma.o
+obj-$(CONFIG_LOONGSON2_APB_CMC_DMA) += loongson2-apb-dmamux.o
diff --git a/drivers/dma/loongson/loongson2-apb-dmamux.c b/drivers/dma/loongson/loongson2-apb-dmamux.c
new file mode 100644
index 000000000000..01bd3ce4ca25
--- /dev/null
+++ b/drivers/dma/loongson/loongson2-apb-dmamux.c
@@ -0,0 +1,398 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Loongson2 SoC APB DMA Mux Controller
+ *
+ * Copyright (C) 2026 Loongson Technology Corporation Limited
+ *
+ * Device tree bindings:
+ *
+ * 2K0300:
+ * dma_mux: dma-mux@16000134 {
+ * compatible = "loongson,ls2k0300-dmamux";
+ * reg = <0x0 0x16000134 0x0 0xc>;
+ * #dma-cells = <3>;
+ * dma-masters = <&dma>;
+ * dma-requests = <22>;
+ * };
+ *
+ * DMA specifier: <request> <channel> <flags>
+ * - request: peripheral request ID (LS2K0300_DMA_*)
+ * - channel: target physical DMA channel
+ * - flags: channel configuration flags forwarded to the parent DMA
+ * controller
+ */
+
+#include <linux/bitfield.h>
+#include <linux/cleanup.h>
+#include <linux/device.h>
+#include <linux/dmaengine.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_dma.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+
+#include <dt-bindings/dma/loongson,ls2k-dmamux.h>
+
+/* Loongson-2K0300 registers definitions */
+#define LS2K0300_CHIP_CTRL13 0x00
+#define LS2K0300_CHIP_CTRL14 0x04
+#define LS2K0300_CHIP_CTRL15 0x08
+
+/* CHIP_CTRL13 bitfields */
+#define CTRL13_UART0_DMA_MAP GENMASK(17, 16)
+#define CTRL13_UART1_DMA_MAP GENMASK(19, 18)
+#define CTRL13_UART2_DMA_MAP GENMASK(21, 20)
+#define CTRL13_UART3_DMA_MAP GENMASK(23, 22)
+#define CTRL13_UART4_DMA_MAP GENMASK(25, 24)
+#define CTRL13_UART5_DMA_MAP GENMASK(27, 26)
+#define CTRL13_UART6_DMA_MAP GENMASK(29, 28)
+#define CTRL13_UART7_DMA_MAP GENMASK(31, 30)
+
+/* CHIP_CTRL14 bitfields */
+#define CTRL14_UART8_DMA_MAP GENMASK(1, 0)
+#define CTRL14_UART9_DMA_MAP GENMASK(3, 2)
+#define CTRL14_I2C0_DMA_MAP GENMASK(5, 4)
+#define CTRL14_I2C1_DMA_MAP GENMASK(7, 6)
+#define CTRL14_I2C2_DMA_MAP GENMASK(9, 8)
+#define CTRL14_I2C3_DMA_MAP GENMASK(11, 10)
+#define CTRL14_SPI2_DMA_MAP GENMASK(13, 12)
+#define CTRL14_SPI3_DMA_MAP GENMASK(15, 14)
+#define CTRL14_I2S_DMA_MAP GENMASK(17, 16)
+#define CTRL14_ADC_DMA_MAP GENMASK(20, 18)
+#define CTRL14_CAN0_DMA_MAP GENMASK(23, 21)
+#define CTRL14_CAN1_DMA_MAP GENMASK(26, 24)
+#define CTRL14_CAN2_DMA_MAP GENMASK(29, 27)
+#define CTRL14_CAN3_DMA_MAP GENMASK(31, 30)
+
+/* CHIP_CTRL15 bitfields */
+#define CTRL15_CAN3_DMA_MAP_HI BIT(0)
+
+#define LS2K0300_DMA_MAX_CHANNEL 7
+
+/**
+ * enum loongson2_dmamux_type - Type of the mapping field
+ * @LOONGSON_DMAMUX_PAIR: 2-bit field, value selects a channel pair
+ * (0/1, 2/3, 4/5, 6/7).
+ * @LOONGSON_DMAMUX_SINGLE: 3-bit field, value selects a single channel
+ * or controller index directly.
+ */
+enum loongson2_dmamux_type {
+ LOONGSON_DMAMUX_PAIR,
+ LOONGSON_DMAMUX_SINGLE,
+};
+
+/**
+ * struct loongson2_dmamux_map - DMA request to register bitfield mapping
+ * @reg: Register offset from the controller base
+ * @mask: Bitfield mask within the register
+ * @type: Mapping type (pair or single)
+ * @high_reg: Optional extension register offset (0 if unused)
+ * @high_shift: Bit position in the extension register
+ */
+struct loongson2_dmamux_map {
+ u32 reg;
+ u32 mask;
+ enum loongson2_dmamux_type type;
+ u32 high_reg;
+ u8 high_shift;
+};
+
+/**
+ * struct loongson2_dmamux_config - SoC-specific DMA mux configuration
+ * @maps: Pointer to the request mapping table
+ * @num_maps: Number of entries in @maps
+ * @max_channel: Highest valid channel/controller index
+ * @parent_args_count: Number of cells to write to dma_spec->args[]
+ * when forwarding to the parent xlate.
+ */
+struct loongson2_dmamux_config {
+ const struct loongson2_dmamux_map *maps;
+ u32 num_maps;
+ u32 max_channel;
+ u32 parent_args_count;
+};
+
+/**
+ * struct loongson2_dmamux - DMA mux controller state
+ * @base: I/O-mapped register base
+ * @lock: Protects register read-modify-write sequences
+ * @dma_router: Router structure passed to of_dma_router_register()
+ * @config: SoC-specific configuration
+ */
+struct loongson2_dmamux {
+ void __iomem *base;
+ spinlock_t lock; /* Protects register read-modify-write sequences */
+ struct dma_router dma_router;
+ const struct loongson2_dmamux_config *config;
+};
+
+/* Loongson-2K0300 mapping table */
+static const struct loongson2_dmamux_map ls2k0300_dmamux_maps[] = {
+ [LS2K0300_DMA_UART0] = { LS2K0300_CHIP_CTRL13, CTRL13_UART0_DMA_MAP, LOONGSON_DMAMUX_PAIR,
+ 0, 0 },
+ [LS2K0300_DMA_UART1] = { LS2K0300_CHIP_CTRL13, CTRL13_UART1_DMA_MAP, LOONGSON_DMAMUX_PAIR,
+ 0, 0 },
+ [LS2K0300_DMA_UART2] = { LS2K0300_CHIP_CTRL13, CTRL13_UART2_DMA_MAP, LOONGSON_DMAMUX_PAIR,
+ 0, 0 },
+ [LS2K0300_DMA_UART3] = { LS2K0300_CHIP_CTRL13, CTRL13_UART3_DMA_MAP, LOONGSON_DMAMUX_PAIR,
+ 0, 0 },
+ [LS2K0300_DMA_UART4] = { LS2K0300_CHIP_CTRL13, CTRL13_UART4_DMA_MAP, LOONGSON_DMAMUX_PAIR,
+ 0, 0 },
+ [LS2K0300_DMA_UART5] = { LS2K0300_CHIP_CTRL13, CTRL13_UART5_DMA_MAP, LOONGSON_DMAMUX_PAIR,
+ 0, 0 },
+ [LS2K0300_DMA_UART6] = { LS2K0300_CHIP_CTRL13, CTRL13_UART6_DMA_MAP, LOONGSON_DMAMUX_PAIR,
+ 0, 0 },
+ [LS2K0300_DMA_UART7] = { LS2K0300_CHIP_CTRL13, CTRL13_UART7_DMA_MAP, LOONGSON_DMAMUX_PAIR,
+ 0, 0 },
+ [LS2K0300_DMA_UART8] = { LS2K0300_CHIP_CTRL14, CTRL14_UART8_DMA_MAP, LOONGSON_DMAMUX_PAIR,
+ 0, 0 },
+ [LS2K0300_DMA_UART9] = { LS2K0300_CHIP_CTRL14, CTRL14_UART9_DMA_MAP, LOONGSON_DMAMUX_PAIR,
+ 0, 0 },
+ [LS2K0300_DMA_I2C0] = { LS2K0300_CHIP_CTRL14, CTRL14_I2C0_DMA_MAP, LOONGSON_DMAMUX_PAIR,
+ 0, 0 },
+ [LS2K0300_DMA_I2C1] = { LS2K0300_CHIP_CTRL14, CTRL14_I2C1_DMA_MAP, LOONGSON_DMAMUX_PAIR,
+ 0, 0 },
+ [LS2K0300_DMA_I2C2] = { LS2K0300_CHIP_CTRL14, CTRL14_I2C2_DMA_MAP, LOONGSON_DMAMUX_PAIR,
+ 0, 0 },
+ [LS2K0300_DMA_I2C3] = { LS2K0300_CHIP_CTRL14, CTRL14_I2C3_DMA_MAP, LOONGSON_DMAMUX_PAIR,
+ 0, 0 },
+ [LS2K0300_DMA_SPI2] = { LS2K0300_CHIP_CTRL14, CTRL14_SPI2_DMA_MAP, LOONGSON_DMAMUX_PAIR,
+ 0, 0 },
+ [LS2K0300_DMA_SPI3] = { LS2K0300_CHIP_CTRL14, CTRL14_SPI3_DMA_MAP, LOONGSON_DMAMUX_PAIR,
+ 0, 0 },
+ [LS2K0300_DMA_I2S] = { LS2K0300_CHIP_CTRL14, CTRL14_I2S_DMA_MAP, LOONGSON_DMAMUX_PAIR,
+ 0, 0 },
+ [LS2K0300_DMA_ADC] = { LS2K0300_CHIP_CTRL14, CTRL14_ADC_DMA_MAP, LOONGSON_DMAMUX_SINGLE,
+ 0, 0 },
+ [LS2K0300_DMA_CAN0] = { LS2K0300_CHIP_CTRL14, CTRL14_CAN0_DMA_MAP, LOONGSON_DMAMUX_SINGLE,
+ 0, 0 },
+ [LS2K0300_DMA_CAN1] = { LS2K0300_CHIP_CTRL14, CTRL14_CAN1_DMA_MAP, LOONGSON_DMAMUX_SINGLE,
+ 0, 0 },
+ [LS2K0300_DMA_CAN2] = { LS2K0300_CHIP_CTRL14, CTRL14_CAN2_DMA_MAP, LOONGSON_DMAMUX_SINGLE,
+ 0, 0 },
+ [LS2K0300_DMA_CAN3] = { LS2K0300_CHIP_CTRL14, CTRL14_CAN3_DMA_MAP, LOONGSON_DMAMUX_SINGLE,
+ LS2K0300_CHIP_CTRL15, 0 },
+};
+
+static const struct loongson2_dmamux_config ls2k0300_dmamux_config = {
+ .maps = ls2k0300_dmamux_maps,
+ .num_maps = ARRAY_SIZE(ls2k0300_dmamux_maps),
+ .max_channel = LS2K0300_DMA_MAX_CHANNEL,
+ .parent_args_count = 2,
+};
+
+static inline u32 loongson2_dmamux_read(struct loongson2_dmamux *mux, u32 reg)
+{
+ return readl(mux->base + reg);
+}
+
+static inline void loongson2_dmamux_write(struct loongson2_dmamux *mux, u32 reg, u32 val)
+{
+ writel(val, mux->base + reg);
+}
+
+/**
+ * loongson2_dmamux_set_route() - Program the DMA request route
+ * @mux: DMA mux controller
+ * @request: Peripheral DMA request ID
+ * @channel: Target physical DMA channel or controller index
+ *
+ * Computes the register value according to the mapping type:
+ * - PAIR : channel / 2 selects the pair index
+ * - SINGLE : channel is written directly
+ *
+ * Return: 0 on success, negative error code otherwise.
+ */
+static int loongson2_dmamux_set_route(struct loongson2_dmamux *mux, u32 request, u32 channel)
+{
+ const struct loongson2_dmamux_map *map;
+ u32 reg_val, route_val, high_val = 0;
+
+ if (request >= mux->config->num_maps)
+ return -EINVAL;
+
+ if (channel > mux->config->max_channel)
+ return -EINVAL;
+
+ map = &mux->config->maps[request];
+
+ switch (map->type) {
+ case LOONGSON_DMAMUX_PAIR:
+ route_val = channel / 2;
+ break;
+ case LOONGSON_DMAMUX_SINGLE:
+ route_val = channel;
+ if (map->high_reg)
+ high_val = (channel >> 2) & 0x1;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ guard(spinlock_irqsave)(&mux->lock);
+
+ /* Write the primary register field */
+ reg_val = loongson2_dmamux_read(mux, map->reg);
+ reg_val &= ~map->mask;
+ reg_val |= field_prep(map->mask, route_val);
+ loongson2_dmamux_write(mux, map->reg, reg_val);
+
+ /* Write the extension register field if present */
+ if (map->high_reg) {
+ reg_val = loongson2_dmamux_read(mux, map->high_reg);
+ reg_val &= ~BIT(map->high_shift);
+ reg_val |= high_val << map->high_shift;
+ loongson2_dmamux_write(mux, map->high_reg, reg_val);
+ }
+
+ return 0;
+}
+
+/**
+ * loongson2_dmamux_route_allocate() - DMA router allocation callback
+ * @dma_spec: OF DMA specifier <request> <channel> <flags>
+ * @ofdma: Router's of_dma structure; ofdma->dma_router points to our
+ * struct dma_router embedded in struct loongson2_dmamux.
+ *
+ * Return: NULL as route_data (nothing to free), or an ERR_PTR on failure.
+ */
+static void *loongson2_dmamux_route_allocate(struct of_phandle_args *dma_spec,
+ struct of_dma *ofdma)
+{
+ struct loongson2_dmamux *mux;
+ u32 request, channel, flags;
+ int ret;
+
+ if (!ofdma->dma_router)
+ return ERR_PTR(-EINVAL);
+
+ mux = container_of(ofdma->dma_router, struct loongson2_dmamux, dma_router);
+
+ if (dma_spec->args_count != 3)
+ return ERR_PTR(-EINVAL);
+
+ request = dma_spec->args[0];
+ channel = dma_spec->args[1];
+ flags = dma_spec->args[2];
+
+ if (request >= mux->config->num_maps ||
+ channel > mux->config->max_channel)
+ return ERR_PTR(-EINVAL);
+
+ /* Program the SoC-specific route register */
+ ret = loongson2_dmamux_set_route(mux, request, channel);
+ if (ret)
+ return ERR_PTR(ret);
+
+ /* The of_node_put() will be done in of_dma_router_xlate function */
+ dma_spec->np = of_parse_phandle(ofdma->of_node, "dma-masters", 0);
+ if (!dma_spec->np)
+ return ERR_PTR(-ENODEV);
+
+ dma_spec->args[0] = channel;
+ dma_spec->args[1] = flags;
+ dma_spec->args_count = mux->config->parent_args_count;
+
+ return NULL;
+}
+
+/**
+ * loongson2_dmamux_route_free() - DMA router free callback
+ * @dev: Back pointer to the router's device
+ * @route_data: Router-specific data returned by route_allocate
+ *
+ * The driver does not allocate any per-route resources, so this callback
+ * is intentionally empty. It must still be provided because the OF DMA
+ * core calls it unconditionally on some error paths (e.g. -EPROBE_DEFER)
+ * without checking for a NULL pointer.
+ */
+static void loongson2_dmamux_route_free(struct device *dev, void *route_data)
+{
+}
+
+/**
+ * loongson2_dmamux_unregister_of_dma() - devm action to unregister the router
+ * @data: Pointer to struct loongson2_dmamux
+ *
+ * Called automatically by the device-managed resource framework both on
+ * probe failure and on driver removal, ensuring the OF DMA router is
+ * always unregistered.
+ */
+static void loongson2_dmamux_unregister_of_dma(void *data)
+{
+ struct loongson2_dmamux *mux = data;
+
+ of_dma_router_free(mux->dma_router.dev->of_node);
+}
+
+static int loongson2_dmamux_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct loongson2_dmamux *mux;
+ u32 dma_requests;
+ int ret;
+
+ mux = devm_kzalloc(dev, sizeof(*mux), GFP_KERNEL);
+ if (!mux)
+ return -ENOMEM;
+
+ mux->base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(mux->base))
+ return PTR_ERR(mux->base);
+
+ spin_lock_init(&mux->lock);
+ mux->config = &ls2k0300_dmamux_config;
+
+ ret = of_property_read_u32(dev->of_node, "dma-requests", &dma_requests);
+ if (ret)
+ return dev_err_probe(dev, ret, "missing dma-requests property\n");
+
+ if (dma_requests != mux->config->num_maps)
+ return dev_err_probe(dev, -EINVAL,
+ "dma-requests=%u mismatches driver num_maps=%u",
+ dma_requests, mux->config->num_maps);
+
+ mux->dma_router.dev = dev;
+ mux->dma_router.route_free = loongson2_dmamux_route_free;
+
+ platform_set_drvdata(pdev, mux);
+
+ ret = of_dma_router_register(dev->of_node, loongson2_dmamux_route_allocate,
+ &mux->dma_router);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "Failed to register DMA router");
+
+ ret = devm_add_action_or_reset(dev, loongson2_dmamux_unregister_of_dma, mux);
+ if (ret)
+ return ret;
+
+ dev_info(dev,
+ "Loongson2 DMA Mux Controller registered (max_channel=%u, requests=%u)",
+ mux->config->max_channel, mux->config->num_maps);
+
+ return 0;
+}
+
+static const struct of_device_id loongson2_dmamux_of_match[] = {
+ { .compatible = "loongson,ls2k0300-dmamux" },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, loongson2_dmamux_of_match);
+
+static struct platform_driver loongson2_dmamux_driver = {
+ .driver = {
+ .name = "loongson2-dmamux",
+ .of_match_table = loongson2_dmamux_of_match,
+ },
+ .probe = loongson2_dmamux_probe,
+};
+module_platform_driver(loongson2_dmamux_driver);
+
+MODULE_DESCRIPTION("Loongson2 SoC DMA Mux Controller driver");
+MODULE_AUTHOR("Loongson Technology Corporation Limited");
+MODULE_LICENSE("GPL");
--
2.52.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH v2 1/3] dt-bindings: dma: loongson: Add Loongson-2 DMA mux request IDs
2026-10-09 9:19 ` [PATCH v2 1/3] dt-bindings: dma: loongson: Add Loongson-2 DMA mux request IDs Binbin Zhou
@ 2026-10-09 14:38 ` Conor Dooley
0 siblings, 0 replies; 6+ messages in thread
From: Conor Dooley @ 2026-10-09 14:38 UTC (permalink / raw)
To: Binbin Zhou
Cc: Binbin Zhou, Huacai Chen, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Vinod Koul, Frank Li, dmaengine, Huacai Chen,
Xuerui Wang, loongarch, devicetree, Keguang Zhang
[-- Attachment #1: Type: text/plain, Size: 3381 bytes --]
On Fri, Oct 09, 2026 at 05:19:32PM +0800, Binbin Zhou wrote:
> Add DT binding constants for the Loongson-2 DMA mux.
>
> The header defines the peripheral request IDs used in the DMA specifier
> <request channel flags> for Loongson-2K0300, covering UART0-9, I2C0-3,
> SPI2/3, I2S, ADC and CAN0-3. It also documents the channel-pair semantics
> for peripherals that use paired DMA channels.
>
> Signed-off-by: Binbin Zhou <zhoubinbin@loongson.cn>
Squash this with the binding patch please.
If checkpatch told you to split this, binding headers are bindings and
such that warning is a false positive.
pw-bot: changes-requested
Thanks,
Conor.
> ---
> MAINTAINERS | 1 +
> .../dt-bindings/dma/loongson,ls2k-dmamux.h | 53 +++++++++++++++++++
> 2 files changed, 54 insertions(+)
> create mode 100644 include/dt-bindings/dma/loongson,ls2k-dmamux.h
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 42f5165019ee..172dde21275f 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -15354,6 +15354,7 @@ F: Documentation/devicetree/bindings/dma/loongson,ls2k0300-dma.yaml
> F: Documentation/devicetree/bindings/dma/loongson,ls2x-apbdma.yaml
> F: drivers/dma/loongson/loongson2-apb-cmc-dma.c
> F: drivers/dma/loongson/loongson2-apb-dma.c
> +F: include/dt-bindings/dma/loongson,ls2k-dmamux.h
>
> LOONGSON LS2X I2C DRIVER
> M: Binbin Zhou <zhoubinbin@loongson.cn>
> diff --git a/include/dt-bindings/dma/loongson,ls2k-dmamux.h b/include/dt-bindings/dma/loongson,ls2k-dmamux.h
> new file mode 100644
> index 000000000000..1e2907ab069d
> --- /dev/null
> +++ b/include/dt-bindings/dma/loongson,ls2k-dmamux.h
> @@ -0,0 +1,53 @@
> +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
> +/*
> + * Loongson-2 SoC DMA Mux dt-bindings
> + *
> + * DMA specifier format:
> + * dmas = <&dma_mux <request> <channel> <flags>>;
> + *
> + * The <channel> cell selects a physical CMC DMA channel (0-7)
> + * For peripherals using channel pairs (UART, I2C, SPI2/3, I2S),
> + * the channel number selects the pair: 0/1 -> pair 0, 2/3 -> pair 1,
> + * 4/5 -> pair 2, 6/7 -> pair 3.
> + *
> + * Copyright (C) 2026 Loongson Technology Corporation Limited
> + */
> +
> +#ifndef _DT_BINDINGS_DMA_LOONGSON_LS2K_DMAMUX_H
> +#define _DT_BINDINGS_DMA_LOONGSON_LS2K_DMAMUX_H
> +
> +/* UART controllers */
> +#define LS2K0300_DMA_UART0 0
> +#define LS2K0300_DMA_UART1 1
> +#define LS2K0300_DMA_UART2 2
> +#define LS2K0300_DMA_UART3 3
> +#define LS2K0300_DMA_UART4 4
> +#define LS2K0300_DMA_UART5 5
> +#define LS2K0300_DMA_UART6 6
> +#define LS2K0300_DMA_UART7 7
> +#define LS2K0300_DMA_UART8 8
> +#define LS2K0300_DMA_UART9 9
> +
> +/* I2C controllers */
> +#define LS2K0300_DMA_I2C0 10
> +#define LS2K0300_DMA_I2C1 11
> +#define LS2K0300_DMA_I2C2 12
> +#define LS2K0300_DMA_I2C3 13
> +
> +/* SPI controllers (IO mode) */
> +#define LS2K0300_DMA_SPI2 14
> +#define LS2K0300_DMA_SPI3 15
> +
> +/* I2S controller */
> +#define LS2K0300_DMA_I2S 16
> +
> +/* ADC controller */
> +#define LS2K0300_DMA_ADC 17
> +
> +/* CAN-FD controllers */
> +#define LS2K0300_DMA_CAN0 18
> +#define LS2K0300_DMA_CAN1 19
> +#define LS2K0300_DMA_CAN2 20
> +#define LS2K0300_DMA_CAN3 21
> +
> +#endif /* _DT_BINDINGS_DMA_LOONGSON_LS2K_DMAMUX_H */
> --
> 2.52.0
>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH v2 2/3] dt-bindings: dma: loongson: Add Loongson-2K0300 DMA mux support
2026-10-09 9:19 ` [PATCH v2 2/3] dt-bindings: dma: loongson: Add Loongson-2K0300 DMA mux support Binbin Zhou
@ 2026-10-09 14:43 ` Conor Dooley
0 siblings, 0 replies; 6+ messages in thread
From: Conor Dooley @ 2026-10-09 14:43 UTC (permalink / raw)
To: Binbin Zhou
Cc: Binbin Zhou, Huacai Chen, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Vinod Koul, Frank Li, dmaengine, Huacai Chen,
Xuerui Wang, loongarch, devicetree, Keguang Zhang
[-- Attachment #1: Type: text/plain, Size: 75 bytes --]
Acked-by: Conor Dooley <conor.dooley@microchip.com>
pw-bot: not-applicable
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2026-10-09 14:43 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-09 9:19 [PATCH v2 0/3] Add Loongson-2K0300 APB DMA mux support Binbin Zhou
2026-10-09 9:19 ` [PATCH v2 1/3] dt-bindings: dma: loongson: Add Loongson-2 DMA mux request IDs Binbin Zhou
2026-10-09 14:38 ` Conor Dooley
2026-10-09 9:19 ` [PATCH v2 2/3] dt-bindings: dma: loongson: Add Loongson-2K0300 DMA mux support Binbin Zhou
2026-10-09 14:43 ` Conor Dooley
2026-10-09 9:19 ` [PATCH v2 3/3] dmaengine: loongson: Add Loongson-2K0300 APB DMA mux driver Binbin Zhou
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.