From patchwork Fri Jun 5 11:39:20 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Caesar Wang X-Patchwork-Id: 6552871 Return-Path: X-Original-To: patchwork-linux-rockchip@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 938ECC0020 for ; Fri, 5 Jun 2015 11:40:34 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id AFC132076E for ; Fri, 5 Jun 2015 11:40:33 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.9]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id B7BC620762 for ; Fri, 5 Jun 2015 11:40:32 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1Z0pzE-0002ru-Dm; Fri, 05 Jun 2015 11:40:32 +0000 Received: from mail-pa0-f43.google.com ([209.85.220.43]) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1Z0pyt-0001aX-Fo; Fri, 05 Jun 2015 11:40:12 +0000 Received: by payr10 with SMTP id r10so49404884pay.1; Fri, 05 Jun 2015 04:39:41 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=gdukUtTeiWzCEYcJ9o8bZA/5mc0pqOofKe0RJnChULE=; b=QPwNRqNq0kEOFcVpby+WzW4RDI7sZWkIbbuNuCOY2IsDdyo4cxR5OHnB/+zfD45YCW 8u69JIowrAq2gV1sEMCAYi7I8UrvHXfaxwWz9zVGkBYkwpoWlxbJnW3ooNVQ2pw20el0 jGQ2z3PK4cN9Ltm4rkCArb63vAwhGj5gKJttLNVDs1iIuXLfsXFxTTUPnOPMxJoVQFQF KN5C5WAcYBvb07U7/r4l3376aTNpg1xw2ZcCoHZFvztlYX0onmMF7LTR/GuQqXmevOa3 4mOIbzCtzmWkumVrdZbPC+mJKjrD9G92rLoD9bXrA6wO6wTizTVQw/bE3e6+JEjiiQYh vK7g== X-Received: by 10.66.222.72 with SMTP id qk8mr5312663pac.7.1433504381149; Fri, 05 Jun 2015 04:39:41 -0700 (PDT) Received: from localhost.localdomain ([191.101.57.89]) by mx.google.com with ESMTPSA id xo3sm6505189pbb.74.2015.06.05.04.39.37 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Fri, 05 Jun 2015 04:39:39 -0700 (PDT) From: Caesar Wang To: Heiko Stuebner Subject: [PATCH v2 1/3] ARM: rockchip: fix the CPU soft reset Date: Fri, 5 Jun 2015 19:39:20 +0800 Message-Id: <1433504362-7549-2-git-send-email-wxt@rock-chips.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1433504362-7549-1-git-send-email-wxt@rock-chips.com> References: <1433504362-7549-1-git-send-email-wxt@rock-chips.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20150605_044011_610830_F886D3C7 X-CRM114-Status: GOOD ( 12.55 ) X-Spam-Score: -1.8 (-) Cc: Russell King , Dmitry Torokhov , dianders@chromium.org, linux-kernel@vger.kernel.org, linux-rockchip@lists.infradead.org, linux-arm-kernel@lists.infradead.org, Caesar Wang X-BeenThere: linux-rockchip@lists.infradead.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: Upstream kernel work for Rockchip platforms List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: "Linux-rockchip" Errors-To: linux-rockchip-bounces+patchwork-linux-rockchip=patchwork.kernel.org@lists.infradead.org X-Spam-Status: No, score=-4.2 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP We need different orderings when turning a core on and turning a core off. In one case we need to assert reset before turning power off. In ther other case we need to turn power on and the deassert reset. In general, the correct flow is: CPU off: reset_control_assert regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), BIT(pd)) wait_for_power_domain_to_turn_off CPU on: regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), 0) wait_for_power_domain_to_turn_on reset_control_deassert This is needed for stressing CPU up/down, as per: cd /sys/devices/system/cpu/ for i in $(seq 1000); do echo "================= $i ============" for j in $(seq 100); do while [[ "$(cat cpu1/online)$(cat cpu2/online)$(cat cpu3/online)" != "000" ]]; do echo 0 > cpu1/online echo 0 > cpu2/online echo 0 > cpu3/online done while [[ "$(cat cpu1/online)$(cat cpu2/online)$(cat cpu3/online)" != "111" ]]; do echo 1 > cpu1/online echo 1 > cpu2/online echo 1 > cpu3/online done done done The following is reproducile log: [34466.186812] PM: noirq suspend of devices complete after 0.669 msecs [34466.186824] Disabling non-boot CPUs ... [34466.187509] CPU1: shutdown [34466.188672] CPU2: shutdown [34473.736627] Kernel panic - not syncing: Watchdog detected hard LOCKUP on cpu 0 ....... Signed-off-by: Caesar Wang --- arch/arm/mach-rockchip/platsmp.c | 46 +++++++++++++++++++++++++++------------- 1 file changed, 31 insertions(+), 15 deletions(-) diff --git a/arch/arm/mach-rockchip/platsmp.c b/arch/arm/mach-rockchip/platsmp.c index 5b4ca3c..1d4659e 100644 --- a/arch/arm/mach-rockchip/platsmp.c +++ b/arch/arm/mach-rockchip/platsmp.c @@ -88,28 +88,44 @@ static int pmu_set_power_domain(int pd, bool on) return PTR_ERR(rstc); } - if (on) - reset_control_deassert(rstc); - else + if (!on) reset_control_assert(rstc); - reset_control_put(rstc); - } + ret = regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), val); + if (ret < 0) { + pr_err("%s: could not update power domain\n", __func__); + reset_control_put(rstc); + return ret; + } - ret = regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), val); - if (ret < 0) { - pr_err("%s: could not update power domain\n", __func__); - return ret; - } + ret = -1; + while (ret != on) { + ret = pmu_power_domain_is_on(pd); + if (ret < 0) { + pr_err("%s: could not read power domain state\n", + __func__); + return ret; + } + } - ret = -1; - while (ret != on) { - ret = pmu_power_domain_is_on(pd); + if (on) + reset_control_deassert(rstc); + } else { + ret = regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), val); if (ret < 0) { - pr_err("%s: could not read power domain state\n", - __func__); + pr_err("%s: could not update power domain\n", __func__); return ret; } + + ret = -1; + while (ret != on) { + ret = pmu_power_domain_is_on(pd); + if (ret < 0) { + pr_err("%s: could not read power domain state\n", + __func__); + return ret; + } + } } return 0;