From ea08eeccae9297f7aabd2ef7f0c2517ac4549acc Mon Sep 17 00:00:00 2001
From: hc <hc@nodka.com>
Date: Tue, 20 Feb 2024 01:18:26 +0000
Subject: [PATCH] write in 30M
---
kernel/drivers/amba/bus.c | 93 +++++++++++++++++++++++++++++++++++++---------
1 files changed, 75 insertions(+), 18 deletions(-)
diff --git a/kernel/drivers/amba/bus.c b/kernel/drivers/amba/bus.c
index e1992f3..52ab582 100644
--- a/kernel/drivers/amba/bus.c
+++ b/kernel/drivers/amba/bus.c
@@ -1,11 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* linux/arch/arm/common/amba.c
*
* Copyright (C) 2003 Deep Blue Solutions Ltd, All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
*/
#include <linux/module.h>
#include <linux/init.h>
@@ -21,24 +18,42 @@
#include <linux/limits.h>
#include <linux/clk/clk-conf.h>
#include <linux/platform_device.h>
+#include <linux/reset.h>
#include <asm/irq.h>
#define to_amba_driver(d) container_of(d, struct amba_driver, drv)
+/* called on periphid match and class 0x9 coresight device. */
+static int
+amba_cs_uci_id_match(const struct amba_id *table, struct amba_device *dev)
+{
+ int ret = 0;
+ struct amba_cs_uci_id *uci;
+
+ uci = table->data;
+
+ /* no table data or zero mask - return match on periphid */
+ if (!uci || (uci->devarch_mask == 0))
+ return 1;
+
+ /* test against read devtype and masked devarch value */
+ ret = (dev->uci.devtype == uci->devtype) &&
+ ((dev->uci.devarch & uci->devarch_mask) == uci->devarch);
+ return ret;
+}
+
static const struct amba_id *
amba_lookup(const struct amba_id *table, struct amba_device *dev)
{
- int ret = 0;
-
while (table->mask) {
- ret = (dev->periphid & table->mask) == table->id;
- if (ret)
- break;
+ if (((dev->periphid & table->mask) == table->id) &&
+ ((dev->cid != CORESIGHT_CID) ||
+ (amba_cs_uci_id_match(table, dev))))
+ return table;
table++;
}
-
- return ret ? table : NULL;
+ return NULL;
}
static int amba_match(struct device *dev, struct device_driver *drv)
@@ -284,11 +299,10 @@
{
struct amba_device *pcdev = to_amba_device(dev);
struct amba_driver *drv = to_amba_driver(dev->driver);
- int ret = 0;
pm_runtime_get_sync(dev);
if (drv->remove)
- ret = drv->remove(pcdev);
+ drv->remove(pcdev);
pm_runtime_put_noidle(dev);
/* Undo the runtime PM settings in amba_probe() */
@@ -299,7 +313,7 @@
amba_put_disable_pclk(pcdev);
dev_pm_domain_detach(dev, true);
- return ret;
+ return 0;
}
static void amba_shutdown(struct device *dev)
@@ -349,6 +363,7 @@
{
struct amba_device *d = to_amba_device(dev);
+ of_node_put(d->dev.of_node);
if (d->res.parent)
release_resource(&d->res);
kfree(d);
@@ -388,6 +403,21 @@
ret = amba_get_enable_pclk(dev);
if (ret == 0) {
u32 pid, cid;
+ struct reset_control *rstc;
+
+ /*
+ * Find reset control(s) of the amba bus and de-assert them.
+ */
+ rstc = of_reset_control_array_get_optional_shared(dev->dev.of_node);
+ if (IS_ERR(rstc)) {
+ ret = PTR_ERR(rstc);
+ if (ret != -EPROBE_DEFER)
+ dev_err(&dev->dev, "can't get reset: %d\n",
+ ret);
+ goto err_reset;
+ }
+ reset_control_deassert(rstc);
+ reset_control_put(rstc);
/*
* Read pid and cid based on size of resource
@@ -400,10 +430,22 @@
cid |= (readl(tmp + size - 0x10 + 4 * i) & 255) <<
(i * 8);
+ if (cid == CORESIGHT_CID) {
+ /* set the base to the start of the last 4k block */
+ void __iomem *csbase = tmp + size - 4096;
+
+ dev->uci.devarch =
+ readl(csbase + UCI_REG_DEVARCH_OFFSET);
+ dev->uci.devtype =
+ readl(csbase + UCI_REG_DEVTYPE_OFFSET) & 0xff;
+ }
+
amba_put_disable_pclk(dev);
- if (cid == AMBA_CID || cid == CORESIGHT_CID)
+ if (cid == AMBA_CID || cid == CORESIGHT_CID) {
dev->periphid = pid;
+ dev->cid = cid;
+ }
if (!dev->periphid)
ret = -ENODEV;
@@ -433,6 +475,12 @@
release_resource(&dev->res);
err_out:
return ret;
+
+ err_reset:
+ amba_put_disable_pclk(dev);
+ iounmap(tmp);
+ dev_pm_domain_detach(&dev->dev, true);
+ goto err_release;
}
/*
@@ -458,7 +506,7 @@
#define DEFERRED_DEVICE_TIMEOUT (msecs_to_jiffies(5 * 1000))
-static void amba_deferred_retry_func(struct work_struct *dummy)
+static int amba_deferred_retry(void)
{
struct deferred_device *ddev, *tmp;
@@ -474,11 +522,19 @@
kfree(ddev);
}
+ mutex_unlock(&deferred_devices_lock);
+
+ return 0;
+}
+late_initcall(amba_deferred_retry);
+
+static void amba_deferred_retry_func(struct work_struct *dummy)
+{
+ amba_deferred_retry();
+
if (!list_empty(&deferred_devices))
schedule_delayed_work(&deferred_retry_work,
DEFERRED_DEVICE_TIMEOUT);
-
- mutex_unlock(&deferred_devices_lock);
}
/**
@@ -598,6 +654,7 @@
dev->dev.release = amba_device_release;
dev->dev.bus = &amba_bustype;
dev->dev.dma_mask = &dev->dev.coherent_dma_mask;
+ dev->dev.dma_parms = &dev->dma_parms;
dev->res.name = dev_name(&dev->dev);
}
--
Gitblit v1.6.2