Received: by 2002:a05:6a10:206:0:0:0:0 with SMTP id 6csp4359882pxj; Tue, 8 Jun 2021 12:22:13 -0700 (PDT) X-Google-Smtp-Source: ABdhPJw9tIKg0u224Sw/vZZ3kZ/1BwKBsZGNgqHc69Wdsqb2I8nELCNz7h3TEQ+7qIqLK98gzSyR X-Received: by 2002:a17:907:990f:: with SMTP id ka15mr24932098ejc.132.1623180132891; Tue, 08 Jun 2021 12:22:12 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1623180132; cv=none; d=google.com; s=arc-20160816; b=m869XyEf+H8ZdwqiY4zZ2VgjBPXZnSZbI0Bg5+5AGB/uRR0DJh4IcjxdkqZaxwpDQ7 pJd1GgUpLy/q4EDW8bbA/VmA+jWvl/MEaOX5QVMV7MKgW6ygohfHSfkRD+2sPgFlWxub YqEUclIYWPxkIk/3rJlA4GG5xLPFeOvV9E/Yoc2A/CiMD/zDLzKHQDv9Spvpa8C1dqRR g8ag3n5BAAUhUc7OSdNgjP7CC0BA12Q0GL+IpF9pJgj5fMxRwzHMKaDRJivCtPpMLMXb ePURtssrcBTMtRGTwiwRhEsucwxALW4pQRoHcAUZnRA/c6ZXGMyy52PzMmrpwn6P9MD3 QTcQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=1MYrIPt0KnTegkRex8iPw/W+z+3G6mOxK5k3Z94mu4s=; b=IDS2+IRD0xmr5Vec8aQxLEAUsVey2ZVZzLQRJm6F2lXWjebHziFvBPW1WPqy4EFHgH YqJyd+N07Xjgrlm0qQv6Ts43CYocyWrAahizM9V0nIz0RlWwEnUqULQj+pkxoOkEUQ4J d1zqViBFE4hFWqx71ybXJ/hZiZK3XAwP/phc7Ye381Iik/0HwCop9K/F+m8LZtWoalKS mKxux0XvJTzPzAqw1Rfw88q0fr/IfvvTCIGG+jJ34MwO/3kX3AllwPY1pysP5JyQ1MWG KWyRzhRYLi9uy3YoQKNwdbKOyu4mSkhNiTCPDSqCEUX65WgrquQsk4rjAYxtNco7rrKO sDpQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=XEk4wk+p; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id e22si431530ejm.605.2021.06.08.12.21.49; Tue, 08 Jun 2021 12:22:12 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=XEk4wk+p; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S239022AbhFHTUx (ORCPT + 99 others); Tue, 8 Jun 2021 15:20:53 -0400 Received: from mail.kernel.org ([198.145.29.99]:53504 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236347AbhFHTJE (ORCPT ); Tue, 8 Jun 2021 15:09:04 -0400 Received: by mail.kernel.org (Postfix) with ESMTPSA id 3D71361027; Tue, 8 Jun 2021 18:47:57 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=linuxfoundation.org; s=korg; t=1623178077; bh=6KshZUQDtbu1sKvreYNSK6mM5Rt9oPAV4HI+Rh5mYsM=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=XEk4wk+pnAc7s+4E5sk27y7x5n4rh4D5hF3679H6iddxEieI4P08zCdgih1I6mqT7 mRVcdoZm1+AMd4+l1d3YKag2KeNw5Sy21suHBV70U97g4RE/zusIcmvfoOopUHe/Xb onJR89eQs9DBc/49pE6JBulMtUZbzY0lfPgueLrM= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Dave Gerlach , Tony Lindgren , Sasha Levin Subject: [PATCH 5.12 068/161] bus: ti-sysc: Fix am335x resume hang for usb otg module Date: Tue, 8 Jun 2021 20:26:38 +0200 Message-Id: <20210608175947.760179341@linuxfoundation.org> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20210608175945.476074951@linuxfoundation.org> References: <20210608175945.476074951@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Tony Lindgren [ Upstream commit 4d7b324e231366ea772ab10df46be31273ca39af ] On am335x, suspend and resume only works once, and the system hangs if suspend is attempted again. However, turns out suspend and resume works fine multiple times if the USB OTG driver for musb controller is loaded. The issue is caused my the interconnect target module losing context during suspend, and it needs a restore on resume to be reconfigure again as debugged earlier by Dave Gerlach . There are also other modules that need a restore on resume, like gpmc as noted by Dave. So let's add a common way to restore an interconnect target module based on a quirk flag. For now, let's enable the quirk for am335x otg only to fix the suspend and resume issue. As gpmc is not causing hangs based on tests with BeagleBone, let's patch gpmc separately. For gpmc, we also need a hardware reset done before restore according to Dave. To reinit the modules, we decouple system suspend from PM runtime. We replace calls to pm_runtime_force_suspend() and pm_runtime_force_resume() with direct calls to internal functions and rely on the driver internal state. There no point trying to handle complex system suspend and resume quirks via PM runtime. This is issue should have already been noticed with commit 1819ef2e2d12 ("bus: ti-sysc: Use swsup quirks also for am335x musb") when quirk handling was added for am335x otg for swsup. But the issue went unnoticed as having musb driver loaded hides the issue, and suspend and resume works once without the driver loaded. Fixes: 1819ef2e2d12 ("bus: ti-sysc: Use swsup quirks also for am335x musb") Suggested-by: Dave Gerlach Signed-off-by: Tony Lindgren Signed-off-by: Sasha Levin --- drivers/bus/ti-sysc.c | 53 +++++++++++++++++++++++++-- include/linux/platform_data/ti-sysc.h | 1 + 2 files changed, 51 insertions(+), 3 deletions(-) diff --git a/drivers/bus/ti-sysc.c b/drivers/bus/ti-sysc.c index 68145e326eb9..49c47b939f21 100644 --- a/drivers/bus/ti-sysc.c +++ b/drivers/bus/ti-sysc.c @@ -1334,6 +1334,34 @@ static int __maybe_unused sysc_runtime_resume(struct device *dev) return error; } +static int sysc_reinit_module(struct sysc *ddata, bool leave_enabled) +{ + struct device *dev = ddata->dev; + int error; + + /* Disable target module if it is enabled */ + if (ddata->enabled) { + error = sysc_runtime_suspend(dev); + if (error) + dev_warn(dev, "reinit suspend failed: %i\n", error); + } + + /* Enable target module */ + error = sysc_runtime_resume(dev); + if (error) + dev_warn(dev, "reinit resume failed: %i\n", error); + + if (leave_enabled) + return error; + + /* Disable target module if no leave_enabled was set */ + error = sysc_runtime_suspend(dev); + if (error) + dev_warn(dev, "reinit suspend failed: %i\n", error); + + return error; +} + static int __maybe_unused sysc_noirq_suspend(struct device *dev) { struct sysc *ddata; @@ -1344,12 +1372,18 @@ static int __maybe_unused sysc_noirq_suspend(struct device *dev) (SYSC_QUIRK_LEGACY_IDLE | SYSC_QUIRK_NO_IDLE)) return 0; - return pm_runtime_force_suspend(dev); + if (!ddata->enabled) + return 0; + + ddata->needs_resume = 1; + + return sysc_runtime_suspend(dev); } static int __maybe_unused sysc_noirq_resume(struct device *dev) { struct sysc *ddata; + int error = 0; ddata = dev_get_drvdata(dev); @@ -1357,7 +1391,19 @@ static int __maybe_unused sysc_noirq_resume(struct device *dev) (SYSC_QUIRK_LEGACY_IDLE | SYSC_QUIRK_NO_IDLE)) return 0; - return pm_runtime_force_resume(dev); + if (ddata->cfg.quirks & SYSC_QUIRK_REINIT_ON_RESUME) { + error = sysc_reinit_module(ddata, ddata->needs_resume); + if (error) + dev_warn(dev, "noirq_resume failed: %i\n", error); + } else if (ddata->needs_resume) { + error = sysc_runtime_resume(dev); + if (error) + dev_warn(dev, "noirq_resume failed: %i\n", error); + } + + ddata->needs_resume = 0; + + return error; } static const struct dev_pm_ops sysc_pm_ops = { @@ -1466,7 +1512,8 @@ static const struct sysc_revision_quirk sysc_revision_quirks[] = { SYSC_QUIRK("usb_otg_hs", 0, 0x400, 0x404, 0x408, 0x00000050, 0xffffffff, SYSC_QUIRK_SWSUP_SIDLE | SYSC_QUIRK_SWSUP_MSTANDBY), SYSC_QUIRK("usb_otg_hs", 0, 0, 0x10, -ENODEV, 0x4ea2080d, 0xffffffff, - SYSC_QUIRK_SWSUP_SIDLE | SYSC_QUIRK_SWSUP_MSTANDBY), + SYSC_QUIRK_SWSUP_SIDLE | SYSC_QUIRK_SWSUP_MSTANDBY | + SYSC_QUIRK_REINIT_ON_RESUME), SYSC_QUIRK("wdt", 0, 0, 0x10, 0x14, 0x502a0500, 0xfffff0f0, SYSC_MODULE_QUIRK_WDT), /* PRUSS on am3, am4 and am5 */ diff --git a/include/linux/platform_data/ti-sysc.h b/include/linux/platform_data/ti-sysc.h index fafc1beea504..9837fb011f2f 100644 --- a/include/linux/platform_data/ti-sysc.h +++ b/include/linux/platform_data/ti-sysc.h @@ -50,6 +50,7 @@ struct sysc_regbits { s8 emufree_shift; }; +#define SYSC_QUIRK_REINIT_ON_RESUME BIT(27) #define SYSC_QUIRK_GPMC_DEBUG BIT(26) #define SYSC_MODULE_QUIRK_ENA_RESETDONE BIT(25) #define SYSC_MODULE_QUIRK_PRUSS BIT(24) -- 2.30.2