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