[RFC PATCH 4/4] serial: 8250: omap: Use reset control for resets

From: Tony Lindgren
Date: Thu Apr 11 2024 - 01:24:46 EST


For at least am335x and omap4, we set the UART_ERRATA_CLOCK_DISABLE quirk
that ends up calling reset for the interconnect target. We can do this with
reset control framework and simplify the 8250_omap driver.

Signed-off-by: Tony Lindgren <tony@xxxxxxxxxxx>
---
drivers/tty/serial/8250/8250_omap.c | 66 +++++++++++------------------
1 file changed, 24 insertions(+), 42 deletions(-)

diff --git a/drivers/tty/serial/8250/8250_omap.c b/drivers/tty/serial/8250/8250_omap.c
--- a/drivers/tty/serial/8250/8250_omap.c
+++ b/drivers/tty/serial/8250/8250_omap.c
@@ -29,6 +29,7 @@
#include <linux/dma-mapping.h>
#include <linux/sys_soc.h>
#include <linux/pm_domain.h>
+#include <linux/reset.h>

#include "8250.h"

@@ -147,6 +148,7 @@ struct omap8250_priv {
struct pm_qos_request pm_qos_request;
struct work_struct qos_work;
struct uart_8250_dma omap8250_dma;
+ struct reset_control *reset;
spinlock_t rx_dma_lock;
bool rx_dma_broken;
bool throttled;
@@ -1490,6 +1492,14 @@ static int omap8250_probe(struct platform_device *pdev)
priv->line = -ENODEV;
priv->latency = PM_QOS_CPU_LATENCY_DEFAULT_VALUE;
priv->calc_latency = PM_QOS_CPU_LATENCY_DEFAULT_VALUE;
+
+ if (priv->habit & UART_ERRATA_CLOCK_DISABLE) {
+ priv->reset = devm_reset_control_get_exclusive(&pdev->dev,
+ "softreset");
+ if (IS_ERR(priv->reset))
+ return PTR_ERR(priv->reset);
+ }
+
cpu_latency_qos_add_request(&priv->pm_qos_request, priv->latency);
INIT_WORK(&priv->qos_work, omap8250_uart_qos_work);

@@ -1695,47 +1705,6 @@ static void uart_write(struct omap8250_priv *priv, u32 reg, u32 val)
writel(val, priv->membase + (reg << OMAP_UART_REGSHIFT));
}

-/* TODO: in future, this should happen via API in drivers/reset/ */
-static int omap8250_soft_reset(struct device *dev)
-{
- struct omap8250_priv *priv = dev_get_drvdata(dev);
- int timeout = 100;
- int sysc;
- int syss;
-
- /*
- * At least on omap4, unused uarts may not idle after reset without
- * a basic scr dma configuration even with no dma in use. The
- * module clkctrl status bits will be 1 instead of 3 blocking idle
- * for the whole clockdomain. The softreset below will clear scr,
- * and we restore it on resume so this is safe to do on all SoCs
- * needing omap8250_soft_reset() quirk. Do it in two writes as
- * recommended in the comment for omap8250_update_scr().
- */
- uart_write(priv, UART_OMAP_SCR, OMAP_UART_SCR_DMAMODE_1);
- uart_write(priv, UART_OMAP_SCR,
- OMAP_UART_SCR_DMAMODE_1 | OMAP_UART_SCR_DMAMODE_CTL);
-
- sysc = uart_read(priv, UART_OMAP_SYSC);
-
- /* softreset the UART */
- sysc |= OMAP_UART_SYSC_SOFTRESET;
- uart_write(priv, UART_OMAP_SYSC, sysc);
-
- /* By experiments, 1us enough for reset complete on AM335x */
- do {
- udelay(1);
- syss = uart_read(priv, UART_OMAP_SYSS);
- } while (--timeout && !(syss & OMAP_UART_SYSS_RESETDONE));
-
- if (!timeout) {
- dev_err(dev, "timed out waiting for reset done\n");
- return -ETIMEDOUT;
- }
-
- return 0;
-}
-
static int omap8250_runtime_suspend(struct device *dev)
{
struct omap8250_priv *priv = dev_get_drvdata(dev);
@@ -1747,7 +1716,20 @@ static int omap8250_runtime_suspend(struct device *dev)
if (priv->habit & UART_ERRATA_CLOCK_DISABLE) {
int ret;

- ret = omap8250_soft_reset(dev);
+ /*
+ * At least on omap4, unused uarts may not idle after reset without
+ * a basic scr dma configuration even with no dma in use. The
+ * module clkctrl status bits will be 1 instead of 3 blocking idle
+ * for the whole clockdomain. The softreset below will clear scr,
+ * and we restore it on resume so this is safe to do on all SoCs
+ * needing omap8250_soft_reset() quirk. Do it in two writes as
+ * recommended in the comment for omap8250_update_scr().
+ */
+ uart_write(priv, UART_OMAP_SCR, OMAP_UART_SCR_DMAMODE_1);
+ uart_write(priv, UART_OMAP_SCR,
+ OMAP_UART_SCR_DMAMODE_1 | OMAP_UART_SCR_DMAMODE_CTL);
+
+ ret = reset_control_reset(priv->reset);
if (ret)
return ret;

--
2.44.0