Received: by 2002:a25:8b91:0:0:0:0:0 with SMTP id j17csp3092799ybl; Sun, 12 Jan 2020 09:33:31 -0800 (PST) X-Google-Smtp-Source: APXvYqwLvaPmEcT70mYiT6SSoOBk+2dnrGe2FCKQgV5BaFcG78/jZtvdWcAlps9lh+SnwAOX9g07 X-Received: by 2002:a54:4396:: with SMTP id u22mr10211969oiv.128.1578850411072; Sun, 12 Jan 2020 09:33:31 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1578850411; cv=none; d=google.com; s=arc-20160816; b=fIlMLiiRD8a382RbKHtFGqtn72gweup3TsaKK3nby1KG2EuH2rGgKgWT98jOVorraw dg9b1sCd0t01qv4RnGSGP1Pz6Y3SkZhL9IWvX+HEdL4zlax2VdfIE3v7rTd+ffg53OZ5 kJWZnUWGKf8U/NAECg4x2RfL4ZlAU1ve9wE5FMrKkSneH39VUQlDOhRBeIPcrpsYm01H 7sg1enyrBvaU7CLMNnSNY+9bpWYQG2HYsUWpT9Z2bRHpVpZHNn38POr7jeIBDeuXJMs0 HDhFiiicIJlCmzkDDU2rpD3xd3yQogruqP9lChhiq/y5zjjyT1s72Sz+9UVdiMZY4yE4 qpBw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=hP6SWGBrH3rl2FCQVrqhJx1xeutc1Bk8aKbd+Ff6RwI=; b=IF4ahOF/hpI4qXifG7Y5sL9GH6yuyDSi6Kq5QRUjic4D0YaE4d7Ba7+F7nypnGPbLP 4P02H0arLeRvUVKBBN/Sbin41ZqiD8IKbQ6Uvs1geWH+3BqhZEyH7Grg+A2MILbtNj59 m+30QVOJiIUBtM7OKDkOCBZkjH+1n+JkdLQMZ5LgVIlZDYIKGEDDkJ/pF3qgclNCEpT8 iUTfxyxfVimY+dGNkgMY9WDiyVW+94LpsusWT3TGrBJh/LdPQXGbM9pkwBWB89r/AyfN U4xG16J5NSTgut4xVNbaLL7Z+14ZKzw0/OldFOBLFC23y29YsJ3XTNtR2cAXyK6LqrDJ RQ+Q== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20161025 header.b=ITKybEv1; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id h8si4570492oib.104.2020.01.12.09.33.19; Sun, 12 Jan 2020 09:33:31 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@gmail.com header.s=20161025 header.b=ITKybEv1; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1733270AbgALRcJ (ORCPT + 99 others); Sun, 12 Jan 2020 12:32:09 -0500 Received: from mail-lf1-f68.google.com ([209.85.167.68]:42255 "EHLO mail-lf1-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1733181AbgALRbl (ORCPT ); Sun, 12 Jan 2020 12:31:41 -0500 Received: by mail-lf1-f68.google.com with SMTP id y19so5143165lfl.9; Sun, 12 Jan 2020 09:31:39 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=hP6SWGBrH3rl2FCQVrqhJx1xeutc1Bk8aKbd+Ff6RwI=; b=ITKybEv1+OYMi4vf5MY2izQ8qFZzQ/0JQOAfPReknecvap6sAqT3vRjrsBzsvj/II0 OxIdqONU+jLgycxO5bzoZqTxP21gyw8imfbzbgdZVASQuCv6GERPin5sLoJ1JYfy9zVq u3N+tmnMg+6zbSLIrGgHeXuLXJHEI0tUVdzmPox5QIevyAsHJ9UWI2i/BOuZB4oJYrmG IoJ+labmiOrZtUuigDDXnN41gvocRgDO5SY/OeWyjrXL7V6x1ytFKFg1HI+mSGeVhpjU bi6a+3QDrprdR5pHMjE8nMuSXk0As9PV/siVenMufIFdhyHauhlWOkGMKdOJHQBaNSo3 KXtA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=hP6SWGBrH3rl2FCQVrqhJx1xeutc1Bk8aKbd+Ff6RwI=; b=IYEJ0UBFXEpU7QJwPaJckRhpzlOGDThSN3wxj+5Nh5Kd9cUJATmuH+cycIrRIFSwid nkWvYDPSmiYf0oXatfkcKUz+B8NV7sdAdUUijmRlShFMqGsl2yNxDCWJS0wP4kvHhCIf Dk8vnvlOV/muNKPaqk+KQXe92MF3wkiGiLxW6TqW2f8ifLMaMOKt43hZOVSySk+ynJ2t /L/zSxyLRoDWevcwAWWQbwGJpDH0iBWczR2cvYSbkj5TSd/jQ5KrTgsFxH6aQoE3zEue oiJG9VWj5a77lORko88WPhXutJIjoqbSm5kdd3FgukpEbkUiasHKEWFhTuJmpX0Wg3l1 Vokw== X-Gm-Message-State: APjAAAWR0ji2da8jxDHHLR367w35T30eUqmIL7PbbSSVmRYp99yQQl3Y JUFmC5BL1hjsXdX0/Vij3lo= X-Received: by 2002:a19:c648:: with SMTP id w69mr7571785lff.44.1578850298922; Sun, 12 Jan 2020 09:31:38 -0800 (PST) Received: from localhost.localdomain (79-139-233-37.dynamic.spd-mgts.ru. [79.139.233.37]) by smtp.gmail.com with ESMTPSA id 140sm4458888lfk.78.2020.01.12.09.31.37 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 12 Jan 2020 09:31:38 -0800 (PST) From: Dmitry Osipenko To: Laxman Dewangan , Vinod Koul , Dan Williams , Thierry Reding , Jonathan Hunter , =?UTF-8?q?Micha=C5=82=20Miros=C5=82aw?= Cc: dmaengine@vger.kernel.org, linux-tegra@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v4 11/14] dmaengine: tegra-apb: Clean up suspend-resume Date: Sun, 12 Jan 2020 20:30:03 +0300 Message-Id: <20200112173006.29863-12-digetx@gmail.com> X-Mailer: git-send-email 2.24.0 In-Reply-To: <20200112173006.29863-1-digetx@gmail.com> References: <20200112173006.29863-1-digetx@gmail.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org It is enough to check whether hardware is busy on suspend and to reset it across of suspend-resume because channel's configuration is fully re-programmed on each DMA transaction anyways and because save-restore of an active channel won't end up well without pausing transfer prior to saving of the state (note that all channels shall be idling at the time of suspend, so save-restore is not needed at all). Signed-off-by: Dmitry Osipenko --- drivers/dma/tegra20-apb-dma.c | 131 +++++++++++++++++----------------- 1 file changed, 67 insertions(+), 64 deletions(-) diff --git a/drivers/dma/tegra20-apb-dma.c b/drivers/dma/tegra20-apb-dma.c index b9d8e57eaf54..398a0e1d6506 100644 --- a/drivers/dma/tegra20-apb-dma.c +++ b/drivers/dma/tegra20-apb-dma.c @@ -1392,6 +1392,36 @@ static const struct tegra_dma_chip_data tegra148_dma_chip_data = { .support_separate_wcount_reg = true, }; +static int tegra_dma_init_hw(struct tegra_dma *tdma) +{ + int err; + + err = reset_control_assert(tdma->rst); + if (err) { + dev_err(tdma->dev, "failed to assert reset: %d\n", err); + return err; + } + + err = clk_enable(tdma->dma_clk); + if (err) { + dev_err(tdma->dev, "failed to enable clk: %d\n", err); + return err; + } + + /* reset DMA controller */ + udelay(2); + reset_control_deassert(tdma->rst); + + /* enable global DMA registers */ + tdma_write(tdma, TEGRA_APBDMA_GENERAL, TEGRA_APBDMA_GENERAL_ENABLE); + tdma_write(tdma, TEGRA_APBDMA_CONTROL, 0); + tdma_write(tdma, TEGRA_APBDMA_IRQ_MASK_SET, 0xFFFFFFFF); + + clk_disable(tdma->dma_clk); + + return 0; +} + static int tegra_dma_probe(struct platform_device *pdev) { const struct tegra_dma_chip_data *cdata; @@ -1433,30 +1463,18 @@ static int tegra_dma_probe(struct platform_device *pdev) if (ret) return ret; + ret = tegra_dma_init_hw(tdma); + if (ret) + goto err_clk_unprepare; + pm_runtime_irq_safe(&pdev->dev); pm_runtime_enable(&pdev->dev); if (!pm_runtime_enabled(&pdev->dev)) { ret = tegra_dma_runtime_resume(&pdev->dev); if (ret) goto err_clk_unprepare; - } else { - ret = pm_runtime_get_sync(&pdev->dev); - if (ret < 0) - goto err_pm_disable; } - /* Reset DMA controller */ - reset_control_assert(tdma->rst); - udelay(2); - reset_control_deassert(tdma->rst); - - /* Enable global DMA registers */ - tdma_write(tdma, TEGRA_APBDMA_GENERAL, TEGRA_APBDMA_GENERAL_ENABLE); - tdma_write(tdma, TEGRA_APBDMA_CONTROL, 0); - tdma_write(tdma, TEGRA_APBDMA_IRQ_MASK_SET, 0xFFFFFFFFul); - - pm_runtime_put(&pdev->dev); - INIT_LIST_HEAD(&tdma->dma_dev.channels); for (i = 0; i < cdata->nr_channels; i++) { struct tegra_dma_channel *tdc = &tdma->channels[i]; @@ -1583,26 +1601,6 @@ static int tegra_dma_remove(struct platform_device *pdev) static int tegra_dma_runtime_suspend(struct device *dev) { struct tegra_dma *tdma = dev_get_drvdata(dev); - unsigned int i; - - tdma->reg_gen = tdma_read(tdma, TEGRA_APBDMA_GENERAL); - for (i = 0; i < tdma->chip_data->nr_channels; i++) { - struct tegra_dma_channel *tdc = &tdma->channels[i]; - struct tegra_dma_channel_regs *ch_reg = &tdc->channel_reg; - - /* Only save the state of DMA channels that are in use */ - if (!tdc->config_init) - continue; - - ch_reg->csr = tdc_read(tdc, TEGRA_APBDMA_CHAN_CSR); - ch_reg->ahb_ptr = tdc_read(tdc, TEGRA_APBDMA_CHAN_AHBPTR); - ch_reg->apb_ptr = tdc_read(tdc, TEGRA_APBDMA_CHAN_APBPTR); - ch_reg->ahb_seq = tdc_read(tdc, TEGRA_APBDMA_CHAN_AHBSEQ); - ch_reg->apb_seq = tdc_read(tdc, TEGRA_APBDMA_CHAN_APBSEQ); - if (tdma->chip_data->support_separate_wcount_reg) - ch_reg->wcount = tdc_read(tdc, - TEGRA_APBDMA_CHAN_WCOUNT); - } clk_disable(tdma->dma_clk); @@ -1612,46 +1610,51 @@ static int tegra_dma_runtime_suspend(struct device *dev) static int tegra_dma_runtime_resume(struct device *dev) { struct tegra_dma *tdma = dev_get_drvdata(dev); - unsigned int i; - int ret; - ret = clk_enable(tdma->dma_clk); - if (ret < 0) { - dev_err(dev, "clk_enable failed: %d\n", ret); - return ret; - } + return clk_enable(tdma->dma_clk); +} - tdma_write(tdma, TEGRA_APBDMA_GENERAL, tdma->reg_gen); - tdma_write(tdma, TEGRA_APBDMA_CONTROL, 0); - tdma_write(tdma, TEGRA_APBDMA_IRQ_MASK_SET, 0xFFFFFFFFul); +static int __maybe_unused tegra_dma_dev_suspend(struct device *dev) +{ + struct tegra_dma *tdma = dev_get_drvdata(dev); + unsigned long flags; + unsigned int i; + bool busy; for (i = 0; i < tdma->chip_data->nr_channels; i++) { struct tegra_dma_channel *tdc = &tdma->channels[i]; - struct tegra_dma_channel_regs *ch_reg = &tdc->channel_reg; - - /* Only restore the state of DMA channels that are in use */ - if (!tdc->config_init) - continue; - - if (tdma->chip_data->support_separate_wcount_reg) - tdc_write(tdc, TEGRA_APBDMA_CHAN_WCOUNT, - ch_reg->wcount); - tdc_write(tdc, TEGRA_APBDMA_CHAN_APBSEQ, ch_reg->apb_seq); - tdc_write(tdc, TEGRA_APBDMA_CHAN_APBPTR, ch_reg->apb_ptr); - tdc_write(tdc, TEGRA_APBDMA_CHAN_AHBSEQ, ch_reg->ahb_seq); - tdc_write(tdc, TEGRA_APBDMA_CHAN_AHBPTR, ch_reg->ahb_ptr); - tdc_write(tdc, TEGRA_APBDMA_CHAN_CSR, - ch_reg->csr & ~TEGRA_APBDMA_CSR_ENB); + + spin_lock_irqsave(&tdc->lock, flags); + busy = tdc->busy; + spin_unlock_irqrestore(&tdc->lock, flags); + + if (busy) { + dev_err(tdma->dev, "channel %u busy\n", i); + return -EBUSY; + } + + tasklet_kill(&tdc->tasklet); } - return 0; + return pm_runtime_force_suspend(dev); +} + +static int __maybe_unused tegra_dma_dev_resume(struct device *dev) +{ + struct tegra_dma *tdma = dev_get_drvdata(dev); + int err; + + err = tegra_dma_init_hw(tdma); + if (err) + return err; + + return pm_runtime_force_resume(dev); } static const struct dev_pm_ops tegra_dma_dev_pm_ops = { SET_RUNTIME_PM_OPS(tegra_dma_runtime_suspend, tegra_dma_runtime_resume, NULL) - SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, - pm_runtime_force_resume) + SET_SYSTEM_SLEEP_PM_OPS(tegra_dma_dev_suspend, tegra_dma_dev_resume) }; static const struct of_device_id tegra_dma_of_match[] = { -- 2.24.0