summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSasha Finkelstein <k@chaosmail.tech>2026-08-15 12:41:39 +0200
committerVinod Koul <vkoul@kernel.org>2026-09-09 19:06:50 +0530
commita1e078d3fca512fd77a531a1dfbcf5bf783e1ea5 (patch)
treee5b8d0a29a998ae72b0b5587ec6a2f8e1ce84030
parentd246fbf92ee22b84f13a339e629ad1dd7ad12f59 (diff)
downloadlinux-next-a1e078d3fca512fd77a531a1dfbcf5bf783e1ea5.tar.gz
linux-next-a1e078d3fca512fd77a531a1dfbcf5bf783e1ea5.zip
dmaengine: apple-admac: Add M3 generation ADMACs
The admacs present on t8122 and t603x SoCs need additional writes in order to operate correctly. The exact purpose of this register is unknown Signed-off-by: Sasha Finkelstein <k@chaosmail.tech> Reviewed-by: Frank Li <Frank.Li@nxp.com> Link: https://patch.msgid.link/20260815-t603x-admac-v4-2-1149e342dcb0@chaosmail.tech Signed-off-by: Vinod Koul <vkoul@kernel.org>
-rw-r--r--drivers/dma/apple-admac.c24
1 files changed, 24 insertions, 0 deletions
diff --git a/drivers/dma/apple-admac.c b/drivers/dma/apple-admac.c
index 14a5ee14a481..9a1c79c12268 100644
--- a/drivers/dma/apple-admac.c
+++ b/drivers/dma/apple-admac.c
@@ -39,10 +39,14 @@
#define FLAG_DESC_NOTIFY BIT(16)
+#define T8122_UNK_28_VAL 0x200000
+
#define REG_TX_START 0x0000
#define REG_TX_STOP 0x0004
#define REG_RX_START 0x0008
#define REG_RX_STOP 0x000c
+#define REG_UNK_28 0x0028
+#define REG_UNK_2C 0x002c
#define REG_IMPRINT 0x0090
#define REG_TX_SRAM_SIZE 0x0094
#define REG_RX_SRAM_SIZE 0x0098
@@ -85,6 +89,10 @@
struct admac_data;
struct admac_tx;
+struct admac_hw {
+ bool set_unk28;
+};
+
struct admac_chan {
unsigned int no;
struct admac_data *host;
@@ -127,6 +135,7 @@ struct admac_data {
struct mutex cache_alloc_lock;
struct admac_sram txcache, rxcache;
+ const struct admac_hw *hw;
int irq;
int irq_index;
int nchannels;
@@ -747,6 +756,11 @@ static int admac_device_config(struct dma_chan *chan,
u32 bus_width = readl_relaxed(ad->base + REG_BUS_WIDTH(adchan->no)) &
~(BUS_WIDTH_WORD_SIZE | BUS_WIDTH_FRAME_SIZE);
+ if (ad->hw->set_unk28) {
+ writel_relaxed(T8122_UNK_28_VAL, ad->base + REG_UNK_28);
+ writel_relaxed(T8122_UNK_28_VAL, ad->base + REG_UNK_2C);
+ }
+
switch (is_tx ? config->dst_addr_width : config->src_addr_width) {
case DMA_SLAVE_BUSWIDTH_1_BYTE:
wordsize = 1;
@@ -800,11 +814,18 @@ static int admac_device_config(struct dma_chan *chan,
return 0;
}
+static const struct admac_hw admac_base_hw = {};
+
+static const struct admac_hw admac_t8122_hw = {
+ .set_unk28 = true,
+};
+
static int admac_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
struct admac_data *ad;
struct dma_device *dma;
+ const struct admac_hw *hw;
int nchannels;
int err, irq, i;
@@ -822,6 +843,8 @@ static int admac_probe(struct platform_device *pdev)
ad->dev = &pdev->dev;
ad->nchannels = nchannels;
mutex_init(&ad->cache_alloc_lock);
+ hw = of_device_get_match_data(&pdev->dev);
+ ad->hw = hw ? hw : &admac_base_hw;
/*
* The controller has 4 IRQ outputs. Try them all until
@@ -936,6 +959,7 @@ static void admac_remove(struct platform_device *pdev)
}
static const struct of_device_id admac_of_match[] = {
+ { .compatible = "apple,t8122-admac", .data = &admac_t8122_hw },
{ .compatible = "apple,t8103-admac", },
{ .compatible = "apple,admac", },
{ }