From 95099d4622f8cb224d94e314c7a8e0df60b13f87 Mon Sep 17 00:00:00 2001
From: hc <hc@nodka.com>
Date: Sat, 09 Dec 2023 08:38:01 +0000
Subject: [PATCH] enable docker ppp

---
 kernel/drivers/dma/pl330.c |  276 ++++++++++++++++++++++++++++++++++++++-----------------
 1 files changed, 190 insertions(+), 86 deletions(-)

diff --git a/kernel/drivers/dma/pl330.c b/kernel/drivers/dma/pl330.c
index 21cfb81..9159280 100644
--- a/kernel/drivers/dma/pl330.c
+++ b/kernel/drivers/dma/pl330.c
@@ -1,16 +1,13 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
 /*
  * Copyright (c) 2012 Samsung Electronics Co., Ltd.
  *		http://www.samsung.com
  *
  * Copyright (C) 2010 Samsung Electronics Co. Ltd.
  *	Jaswinder Singh <jassi.brar@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
  */
 
+#include <linux/debugfs.h>
 #include <linux/kernel.h>
 #include <linux/io.h>
 #include <linux/init.h>
@@ -28,6 +25,7 @@
 #include <linux/err.h>
 #include <linux/pm_runtime.h>
 #include <linux/bug.h>
+#include <linux/reset.h>
 
 #include "dmaengine.h"
 #define PL330_MAX_CHAN		8
@@ -37,16 +35,6 @@
 
 #define PL330_QUIRK_BROKEN_NO_FLUSHP	BIT(0)
 #define PL330_QUIRK_PERIPH_BURST	BIT(1)
-
-#ifdef CONFIG_CPU_RV1126
-#undef writel
-#define writel(v, c)			\
-	do {				\
-		readl_relaxed(c);	\
-		__iowmb();		\
-		writel_relaxed(v, c);	\
-	} while (0)
-#endif
 
 enum pl330_cachectrl {
 	CCTRL0,		/* Noncacheable and nonbufferable */
@@ -268,7 +256,7 @@
 static unsigned cmd_line;
 #define PL330_DBGCMD_DUMP(off, x...)	do { \
 						printk("%x:", cmd_line); \
-						printk(x); \
+						printk(KERN_CONT x); \
 						cmd_line += off; \
 					} while (0)
 #define PL330_DBGMC_START(addr)		(cmd_line = addr)
@@ -298,7 +286,7 @@
 	u32		irq_ns;
 };
 
-/**
+/*
  * Request Configuration.
  * The PL330 core does not modify this and uses the last
  * working configuration if the request doesn't provide any.
@@ -460,8 +448,7 @@
 	/* DMA-mapped view of the FIFO; may differ if an IOMMU is present */
 	dma_addr_t fifo_dma;
 	enum dma_data_direction dir;
-	unsigned int src_interlace_size;
-	unsigned int dst_interlace_size;
+	struct dma_slave_config slave_config;
 
 	/* for runtime pm tracking */
 	bool active;
@@ -470,9 +457,6 @@
 struct pl330_dmac {
 	/* DMA-Engine Device */
 	struct dma_device ddma;
-
-	/* Holds info about sg limitations */
-	struct device_dma_parameters dma_parms;
 
 	/* Pool of descriptors available for the DMAC's channels */
 	struct list_head desc_pool;
@@ -509,6 +493,9 @@
 	unsigned int num_peripherals;
 	struct dma_pl330_chan *peripherals; /* keep at end */
 	int quirks;
+
+	struct reset_control	*rstc;
+	struct reset_control	*rstc_ocp;
 };
 
 static struct pl330_of_quirks {
@@ -554,15 +541,21 @@
 	/* For cyclic capability */
 	bool cyclic;
 	size_t num_periods;
+#ifdef CONFIG_NO_GKI
 	/* interlace size */
 	unsigned int src_interlace_size;
 	unsigned int dst_interlace_size;
+#endif
 };
 
 struct _xfer_spec {
 	u32 ccr;
 	struct dma_pl330_desc *desc;
 };
+
+static int pl330_config_write(struct dma_chan *chan,
+			struct dma_slave_config *slave_config,
+			enum dma_transfer_direction direction);
 
 static inline bool _queue_full(struct pl330_thread *thrd)
 {
@@ -1088,16 +1081,16 @@
 
 		if (_state(thrd) == PL330_STATE_KILLING)
 			UNTIL(thrd, PL330_STATE_STOPPED)
-		/* fall through */
+		fallthrough;
 
 	case PL330_STATE_FAULTING:
 		_stop(thrd);
-		/* fall through */
+		fallthrough;
 
 	case PL330_STATE_KILLING:
 	case PL330_STATE_COMPLETING:
 		UNTIL(thrd, PL330_STATE_STOPPED)
-		/* fall through */
+		fallthrough;
 
 	case PL330_STATE_STOPPED:
 		return _trigger(thrd);
@@ -1148,7 +1141,6 @@
 
 	switch (direction) {
 	case DMA_MEM_TO_MEM:
-		/* fall through */
 	case DMA_MEM_TO_DEV:
 		off += _emit_LD(dry_run, &buf[off], cond);
 		break;
@@ -1182,7 +1174,6 @@
 
 	switch (direction) {
 	case DMA_MEM_TO_MEM:
-		/* fall through */
 	case DMA_DEV_TO_MEM:
 		off += _emit_ST(dry_run, &buf[off], cond);
 		break;
@@ -1227,8 +1218,10 @@
 			pxs->desc->peri);
 		off += _emit_store(dry_run, &buf[off], cond, pxs->desc->rqtype,
 			pxs->desc->peri);
+#ifdef CONFIG_NO_GKI
 		switch (pxs->desc->rqtype) {
 		case DMA_DEV_TO_MEM:
+
 			if (pxs->desc->dst_interlace_size)
 				off += _emit_ADDH(dry_run, &buf[off], DST,
 						  pxs->desc->dst_interlace_size);
@@ -1242,6 +1235,7 @@
 			WARN_ON(1);
 			break;
 		}
+#endif
 	}
 
 	return off;
@@ -1258,7 +1252,6 @@
 
 	switch (pxs->desc->rqtype) {
 	case DMA_MEM_TO_DEV:
-		/* fall through */
 	case DMA_DEV_TO_MEM:
 		off += _ldst_peripheral(pl330, dry_run, &buf[off], pxs, cyc,
 			cond);
@@ -1293,7 +1286,7 @@
 
 	switch (pxs->desc->rqtype) {
 	case DMA_MEM_TO_DEV:
-		/* fall through */
+		fallthrough;
 	case DMA_DEV_TO_MEM:
 		/*
 		 * dregs_len = (total bytes - BURST_TO_BYTE(bursts, ccr)) /
@@ -1457,6 +1450,7 @@
 		off += _emit_LPEND(dry_run, &buf[off], &lpend);
 	}
 
+#ifdef CONFIG_NO_GKI
 	if (!pxs->desc->src_interlace_size &&
 	    !pxs->desc->dst_interlace_size) {
 		num_dregs = BYTE_MOD_BURST_LEN(x->bytes, pxs->ccr);
@@ -1466,6 +1460,14 @@
 			off += _emit_MOV(dry_run, &buf[off], CCR, pxs->ccr);
 		}
 	}
+#else
+	num_dregs = BYTE_MOD_BURST_LEN(x->bytes, pxs->ccr);
+
+	if (num_dregs) {
+		off += _dregs(pl330, dry_run, &buf[off], pxs, num_dregs);
+		off += _emit_MOV(dry_run, &buf[off], CCR, pxs->ccr);
+	}
+#endif
 
 	off += _emit_SEV(dry_run, &buf[off], ev);
 
@@ -1533,21 +1535,26 @@
 		BRST_SIZE(ccr);
 	int off = 0;
 
+#ifdef CONFIG_NO_GKI
 	if (pxs->desc->rqtype == DMA_DEV_TO_MEM)
 		bursts = x->bytes / (BRST_SIZE(ccr) * BRST_LEN(ccr) +
 				     pxs->desc->dst_interlace_size);
 	else if (pxs->desc->rqtype == DMA_MEM_TO_DEV)
 		bursts = x->bytes / (BRST_SIZE(ccr) * BRST_LEN(ccr) +
 				     pxs->desc->src_interlace_size);
+#endif
 	while (bursts) {
 		c = bursts;
 		off += _loop(pl330, dry_run, &buf[off], &c, pxs);
 		bursts -= c;
 	}
+#ifdef CONFIG_NO_GKI
 	if (!pxs->desc->src_interlace_size &&
 	    !pxs->desc->dst_interlace_size)
 		off += _dregs(pl330, dry_run, &buf[off], pxs, num_dregs);
-
+#else
+	off += _dregs(pl330, dry_run, &buf[off], pxs, num_dregs);
+#endif
 	return off;
 }
 
@@ -1578,12 +1585,14 @@
 	unsigned long bursts = BYTE_TO_BURST(x->bytes, ccr);
 	int off = 0;
 
+#ifdef CONFIG_NO_GKI
 	if (pxs->desc->rqtype == DMA_DEV_TO_MEM)
 		bursts = x->bytes / (BRST_SIZE(ccr) * BRST_LEN(ccr)
 			+ pxs->desc->dst_interlace_size);
 	else if (pxs->desc->rqtype == DMA_MEM_TO_DEV)
 		bursts = x->bytes / (BRST_SIZE(ccr) * BRST_LEN(ccr)
 			+ pxs->desc->src_interlace_size);
+#endif
 	/* Setup Loop(s) */
 	off += _loop_cyclic(pl330, dry_run, &buf[off], bursts, pxs, ev);
 
@@ -1767,9 +1776,9 @@
 	tasklet_schedule(&pch->task);
 }
 
-static void pl330_dotask(unsigned long data)
+static void pl330_dotask(struct tasklet_struct *t)
 {
-	struct pl330_dmac *pl330 = (struct pl330_dmac *) data;
+	struct pl330_dmac *pl330 = from_tasklet(pl330, t, tasks);
 	unsigned long flags;
 	int i;
 
@@ -2126,9 +2135,10 @@
 	if (ret) {
 		dev_err(pl330->ddma.dev, "%s:%d Can't to create channels for DMAC!\n",
 			__func__, __LINE__);
-		dma_free_coherent(pl330->ddma.dev,
+		dma_free_attrs(pl330->ddma.dev,
 				chans * pl330->mcbufsz,
-				pl330->mcode_cpu, pl330->mcode_bus);
+				pl330->mcode_cpu, pl330->mcode_bus,
+				DMA_ATTR_PRIVILEGED);
 		return ret;
 	}
 
@@ -2174,7 +2184,7 @@
 		return ret;
 	}
 
-	tasklet_init(&pl330->tasks, pl330_dotask, (unsigned long) pl330);
+	tasklet_setup(&pl330->tasks, pl330_dotask);
 
 	pl330->state = INIT;
 
@@ -2207,9 +2217,9 @@
 	/* Free DMAC resources */
 	dmac_free_threads(pl330);
 
-	dma_free_coherent(pl330->ddma.dev,
+	dma_free_attrs(pl330->ddma.dev,
 		pl330->pcfg.num_chan * pl330->mcbufsz, pl330->mcode_cpu,
-		pl330->mcode_bus);
+		pl330->mcode_bus, DMA_ATTR_PRIVILEGED);
 }
 
 /* forward declaration */
@@ -2257,9 +2267,9 @@
 	}
 }
 
-static void pl330_tasklet(unsigned long data)
+static void pl330_tasklet(struct tasklet_struct *t)
 {
-	struct dma_pl330_chan *pch = (struct dma_pl330_chan *)data;
+	struct dma_pl330_chan *pch = from_tasklet(pch, t, task);
 	struct dma_pl330_desc *desc, *_dt;
 	unsigned long flags;
 	bool power_down = false;
@@ -2367,7 +2377,7 @@
 		return -ENOMEM;
 	}
 
-	tasklet_init(&pch->task, pl330_tasklet, (unsigned long) pch);
+	tasklet_setup(&pch->task, pl330_tasklet);
 
 	spin_unlock_irqrestore(&pl330->lock, flags);
 
@@ -2432,31 +2442,46 @@
 		return max_burst_len;
 }
 
+static int pl330_config_write(struct dma_chan *chan,
+			struct dma_slave_config *slave_config,
+			enum dma_transfer_direction direction)
+{
+	struct dma_pl330_chan *pch = to_pchan(chan);
+
+	pl330_unprep_slave_fifo(pch);
+	if (direction == DMA_MEM_TO_DEV) {
+		if (slave_config->dst_addr)
+			pch->fifo_addr = slave_config->dst_addr;
+		if (slave_config->dst_addr_width)
+			pch->burst_sz = __ffs(slave_config->dst_addr_width);
+#ifdef CONFIG_NO_GKI
+		if (slave_config->src_interlace_size)
+			pch->slave_config.src_interlace_size = slave_config->src_interlace_size;
+#endif
+		pch->burst_len = fixup_burst_len(slave_config->dst_maxburst,
+			pch->dmac->quirks);
+	} else if (direction == DMA_DEV_TO_MEM) {
+		if (slave_config->src_addr)
+			pch->fifo_addr = slave_config->src_addr;
+		if (slave_config->src_addr_width)
+			pch->burst_sz = __ffs(slave_config->src_addr_width);
+#ifdef CONFIG_NO_GKI
+		if (slave_config->dst_interlace_size)
+			pch->slave_config.dst_interlace_size = slave_config->dst_interlace_size;
+#endif
+		pch->burst_len = fixup_burst_len(slave_config->src_maxburst,
+			pch->dmac->quirks);
+	}
+
+	return 0;
+}
+
 static int pl330_config(struct dma_chan *chan,
 			struct dma_slave_config *slave_config)
 {
 	struct dma_pl330_chan *pch = to_pchan(chan);
 
-	pl330_unprep_slave_fifo(pch);
-	if (slave_config->direction == DMA_MEM_TO_DEV) {
-		if (slave_config->dst_addr)
-			pch->fifo_addr = slave_config->dst_addr;
-		if (slave_config->dst_addr_width)
-			pch->burst_sz = __ffs(slave_config->dst_addr_width);
-		if (slave_config->src_interlace_size)
-			pch->src_interlace_size = slave_config->src_interlace_size;
-		pch->burst_len = fixup_burst_len(slave_config->dst_maxburst,
-			pch->dmac->quirks);
-	} else if (slave_config->direction == DMA_DEV_TO_MEM) {
-		if (slave_config->src_addr)
-			pch->fifo_addr = slave_config->src_addr;
-		if (slave_config->src_addr_width)
-			pch->burst_sz = __ffs(slave_config->src_addr_width);
-		if (slave_config->dst_interlace_size)
-			pch->dst_interlace_size = slave_config->dst_interlace_size;
-		pch->burst_len = fixup_burst_len(slave_config->src_maxburst,
-			pch->dmac->quirks);
-	}
+	memcpy(&pch->slave_config, slave_config, sizeof(*slave_config));
 
 	return 0;
 }
@@ -2467,7 +2492,6 @@
 	struct dma_pl330_desc *desc;
 	unsigned long flags;
 	struct pl330_dmac *pl330 = pch->dmac;
-	LIST_HEAD(list);
 	bool power_down = false;
 
 	pm_runtime_get_sync(pl330->ddma.dev);
@@ -2672,7 +2696,7 @@
 	list_splice_tail_init(&pch->submitted_list, &pch->work_list);
 	spin_unlock_irqrestore(&pch->lock, flags);
 
-	pl330_tasklet((unsigned long)pch);
+	pl330_tasklet(&pch->task);
 }
 
 /*
@@ -2776,7 +2800,7 @@
 
 	/* If the DMAC pool is empty, alloc new */
 	if (!desc) {
-		DEFINE_SPINLOCK(lock);
+		static DEFINE_SPINLOCK(lock);
 		LIST_HEAD(pool);
 
 		if (!add_desc(&pool, &lock, GFP_ATOMIC, 1))
@@ -2862,8 +2886,8 @@
 {
 	struct dma_pl330_desc *desc = NULL;
 	struct dma_pl330_chan *pch = to_pchan(chan);
-	dma_addr_t dst;
-	dma_addr_t src;
+	dma_addr_t dst = 0;
+	dma_addr_t src = 0;
 
 	if (len % period_len != 0)
 		return NULL;
@@ -2873,6 +2897,8 @@
 		__func__, __LINE__);
 		return NULL;
 	}
+
+	pl330_config_write(chan, &pch->slave_config, direction);
 
 	if (!pl330_prep_slave_fifo(pch, direction))
 		return NULL;
@@ -2910,10 +2936,10 @@
 	desc->cyclic = true;
 	desc->num_periods = len / period_len;
 	desc->txd.flags = flags;
-
-	desc->src_interlace_size = pch->src_interlace_size;
-	desc->dst_interlace_size = pch->dst_interlace_size;
-
+#ifdef CONFIG_NO_GKI
+	desc->src_interlace_size = pch->slave_config.src_interlace_size;
+	desc->dst_interlace_size = pch->slave_config.dst_interlace_size;
+#endif
 	return &desc->txd;
 }
 
@@ -3004,6 +3030,8 @@
 	if (unlikely(!pch || !sgl || !sg_len))
 		return NULL;
 
+	pl330_config_write(chan, &pch->slave_config, direction);
+
 	if (!pl330_prep_slave_fifo(pch, direction))
 		return NULL;
 
@@ -3044,8 +3072,10 @@
 		desc->rqcfg.brst_len = pch->burst_len;
 		desc->rqtype = direction;
 		desc->bytes_requested = sg_dma_len(sg);
-		desc->src_interlace_size = pch->src_interlace_size;
-		desc->dst_interlace_size = pch->dst_interlace_size;
+#ifdef CONFIG_NO_GKI
+		desc->src_interlace_size = pch->slave_config.src_interlace_size;
+		desc->dst_interlace_size = pch->slave_config.dst_interlace_size;
+#endif
 	}
 
 	/* Return the last desc in the chain */
@@ -3068,6 +3098,55 @@
 	BIT(DMA_SLAVE_BUSWIDTH_4_BYTES) | \
 	BIT(DMA_SLAVE_BUSWIDTH_8_BYTES)
 
+#ifdef CONFIG_DEBUG_FS
+static int pl330_debugfs_show(struct seq_file *s, void *data)
+{
+	struct pl330_dmac *pl330 = s->private;
+	int chans, pchs, ch, pr;
+
+	chans = pl330->pcfg.num_chan;
+	pchs = pl330->num_peripherals;
+
+	seq_puts(s, "PL330 physical channels:\n");
+	seq_puts(s, "THREAD:\t\tCHANNEL:\n");
+	seq_puts(s, "--------\t-----\n");
+	for (ch = 0; ch < chans; ch++) {
+		struct pl330_thread *thrd = &pl330->channels[ch];
+		int found = -1;
+
+		for (pr = 0; pr < pchs; pr++) {
+			struct dma_pl330_chan *pch = &pl330->peripherals[pr];
+
+			if (!pch->thread || thrd->id != pch->thread->id)
+				continue;
+
+			found = pr;
+		}
+
+		seq_printf(s, "%d\t\t", thrd->id);
+		if (found == -1)
+			seq_puts(s, "--\n");
+		else
+			seq_printf(s, "%d\n", found);
+	}
+
+	return 0;
+}
+
+DEFINE_SHOW_ATTRIBUTE(pl330_debugfs);
+
+static inline void init_pl330_debugfs(struct pl330_dmac *pl330)
+{
+	debugfs_create_file(dev_name(pl330->ddma.dev),
+			    S_IFREG | 0444, NULL, pl330,
+			    &pl330_debugfs_fops);
+}
+#else
+static inline void init_pl330_debugfs(struct pl330_dmac *pl330)
+{
+}
+#endif
+
 /*
  * Runtime PM callbacks are provided by amba/bus.c driver.
  *
@@ -3078,12 +3157,7 @@
 {
 	struct amba_device *pcdev = to_amba_device(dev);
 
-	pm_runtime_disable(dev);
-
-	if (!pm_runtime_status_suspended(dev)) {
-		/* amba did not disable the clock */
-		amba_pclk_disable(pcdev);
-	}
+	pm_runtime_force_suspend(dev);
 	amba_pclk_unprepare(pcdev);
 
 	return 0;
@@ -3098,15 +3172,14 @@
 	if (ret)
 		return ret;
 
-	if (!pm_runtime_status_suspended(dev))
-		ret = amba_pclk_enable(pcdev);
-
-	pm_runtime_enable(dev);
+	pm_runtime_force_resume(dev);
 
 	return ret;
 }
 
-static SIMPLE_DEV_PM_OPS(pl330_pm, pl330_suspend, pl330_resume);
+static const struct dev_pm_ops pl330_pm = {
+	SET_LATE_SYSTEM_SLEEP_PM_OPS(pl330_suspend, pl330_resume)
+};
 
 static int
 pl330_probe(struct amba_device *adev, const struct amba_id *id)
@@ -3145,6 +3218,29 @@
 		return PTR_ERR(pl330->base);
 
 	amba_set_drvdata(adev, pl330);
+
+	pl330->rstc = devm_reset_control_get_optional(&adev->dev, "dma");
+	if (IS_ERR(pl330->rstc)) {
+		return dev_err_probe(&adev->dev, PTR_ERR(pl330->rstc), "Failed to get reset!\n");
+	} else {
+		ret = reset_control_deassert(pl330->rstc);
+		if (ret) {
+			dev_err(&adev->dev, "Couldn't deassert the device from reset!\n");
+			return ret;
+		}
+	}
+
+	pl330->rstc_ocp = devm_reset_control_get_optional(&adev->dev, "dma-ocp");
+	if (IS_ERR(pl330->rstc_ocp)) {
+		return dev_err_probe(&adev->dev, PTR_ERR(pl330->rstc_ocp),
+				     "Failed to get OCP reset!\n");
+	} else {
+		ret = reset_control_deassert(pl330->rstc_ocp);
+		if (ret) {
+			dev_err(&adev->dev, "Couldn't deassert the device from OCP reset!\n");
+			return ret;
+		}
+	}
 
 	for (i = 0; i < AMBA_NR_IRQS; i++) {
 		irq = adev->irq[i];
@@ -3242,8 +3338,6 @@
 		}
 	}
 
-	adev->dev.dma_parms = &pl330->dma_parms;
-
 	/*
 	 * This is the limit for transfers with a buswidth of 1, larger
 	 * buswidths will have larger limits.
@@ -3253,6 +3347,7 @@
 		dev_err(&adev->dev, "unable to set the seg size\n");
 
 
+	init_pl330_debugfs(pl330);
 	dev_info(&adev->dev,
 		"Loaded driver for PL330 DMAC-%x\n", adev->periphid);
 	dev_info(&adev->dev,
@@ -3284,10 +3379,15 @@
 probe_err2:
 	pl330_del(pl330);
 
+	if (pl330->rstc_ocp)
+		reset_control_assert(pl330->rstc_ocp);
+
+	if (pl330->rstc)
+		reset_control_assert(pl330->rstc);
 	return ret;
 }
 
-static int pl330_remove(struct amba_device *adev)
+static void pl330_remove(struct amba_device *adev)
 {
 	struct pl330_dmac *pl330 = amba_get_drvdata(adev);
 	struct dma_pl330_chan *pch, *_p;
@@ -3322,7 +3422,11 @@
 
 	pl330_del(pl330);
 
-	return 0;
+	if (pl330->rstc_ocp)
+		reset_control_assert(pl330->rstc_ocp);
+
+	if (pl330->rstc)
+		reset_control_assert(pl330->rstc);
 }
 
 static const struct amba_id pl330_ids[] = {

--
Gitblit v1.6.2