Received: by 2002:ac0:a5a6:0:0:0:0:0 with SMTP id m35-v6csp583648imm; Fri, 14 Sep 2018 03:14:27 -0700 (PDT) X-Google-Smtp-Source: ANB0VdaANhxHorckFB6VT9NSM+yhfuJ2BIKLYrlHzfa5abcRiPyQ9GGtMifPvNqvIirws0tveP5H X-Received: by 2002:a62:1089:: with SMTP id 9-v6mr11814804pfq.30.1536920067866; Fri, 14 Sep 2018 03:14:27 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1536920067; cv=none; d=google.com; s=arc-20160816; b=W4RPUKNbwcWtHqIjjq4o3tfm8iCI3myK6MRISvPVKAYYDIpA7l0buwWNBd04TldkX1 FJDI8MTuQkQPAbUloA5Ucs8DtUtHXFkm7TXM7cOnHmLculCyYhshp/IAB/J6/7byc+D1 EVTXL5huMD3+iH3p4OBjVCXcYWMwYYoYj+/r6Ti5Al/twb/I8iw9cFflAjkOtYsr5jQg 0UhKYwf1SvyO8npd6YSVLslaTdZ87OjM4zzZtIqh0g8JrR6qK5BZMIfoeFMUvdunxpKD 1j9I4N49rQFQKHeGFPqcNBE5oK1bHNdwJWe/NiwicIqZyGRhMdCwTIBgautUmEPx8nex 5T4A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature; bh=8pXDek8ZnrmjczAVnmQjU/AsOxmvJrcBH5KF6yK3Dzk=; b=aGGI0RpCClhd9CyYT9xi6vEDOdbU5oLZyWgAmPP3UMLr7biLXgl50wFU1hUpjA2ISI Ov5msmfEzSYagPGrY8XLOTayupKyB27zsNumWdlIT2fnwpNuC7SEADZMtXNsvXd8uQjA nNVRqUs4Ddv5f1mX2gZwVPNsthG7P6rVB2I/5IIyLQ01TXjBTq5Ojfj0OTpXBPjT4cTQ rfkPSHpYHl5R0yqu0dUkiQPk6jMnpxl4L8SRzDB9QmgArmJW63+cWEVzz/IUd4dVmzcj kcG/ZyThtMJ8bNUeRn+mMZU/AUx/7Z2xyBGvU/OsD7ya1YW0QxtK4XuH+ZONFhkd3o+F jLIA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20161025 header.b=dlb4nVdw; 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 a1-v6si6540235pgg.34.2018.09.14.03.14.12; Fri, 14 Sep 2018 03:14:27 -0700 (PDT) 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=dlb4nVdw; 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 S1728269AbeINP1u (ORCPT + 99 others); Fri, 14 Sep 2018 11:27:50 -0400 Received: from mail-wr1-f65.google.com ([209.85.221.65]:36667 "EHLO mail-wr1-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728165AbeINP1t (ORCPT ); Fri, 14 Sep 2018 11:27:49 -0400 Received: by mail-wr1-f65.google.com with SMTP id e1-v6so9947577wrt.3; Fri, 14 Sep 2018 03:13:58 -0700 (PDT) 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; bh=8pXDek8ZnrmjczAVnmQjU/AsOxmvJrcBH5KF6yK3Dzk=; b=dlb4nVdw5HTnxFtaAsbUYEw+BkbjDdyaJJOuo5wet0S0KlmqJ4lneuPGwg3Tweq8bg x1FyKECxMxWs8uU3Ew0K0T6YFHZWQYdUOvtYwUMsY0KLL23u3fq9WEozgENy9Gsx/QjC B5myXHWfXbXcG1POIqs6qVtphtKHBkbnG1uWOtY35LOEd6VdBm4aYu+C4dN6G8Aa1TKU UJrIE+J31f0uzVBgjWGfQi89XPSalpcwkCVrI4JOK+gXiuUYPo7Qrxt0FmOv8pNVRRW/ dc3P6+7a1V/bmlXrasW6ccNQkeFqhoWjyUw8xxySkwARDu7EBy50edHpM8unup4yVWHw j/bw== 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; bh=8pXDek8ZnrmjczAVnmQjU/AsOxmvJrcBH5KF6yK3Dzk=; b=cCfBHxpxHC00G8svfY3FpE9bV1uXCDJsLnmFcv+2w55r77m0a+mCPrpDG17XvEXzhM +IHQuTjsF7Ay9DmRDiFX+vGIytvdST//tFlKMlGR0KgSgfqPbJHKiJVZ8bGf3xMSgzZA 4CXBMlvqWGrgpHmJiSDYMjBfgfnpdUGq49bi3yGsOaasSJqj4rksKzyFFYrQt/plEqby cpKM8/AnVaW7xD1FrNwkm9fTzcrQMUmQLsFwqZbhytf7M05vs/CDMenxVT9DszidUtJI k01bd93CBLipmDxMA3Hg1t+YsZje1KivKpvch9g2pi4+IuiILsUyRKOH945X+R7dO0L/ Bafg== X-Gm-Message-State: APzg51D3FDR7Ax772+kqEuIfBKSryFiE/NiojuhoXwQtJiHzT36xOSPy BMofO96sNiBDKcY6KvUNlX+T0LZT X-Received: by 2002:adf:959a:: with SMTP id p26-v6mr8542795wrp.202.1536920038176; Fri, 14 Sep 2018 03:13:58 -0700 (PDT) Received: from localhost.localdomain (static-css-cqn-143221.business.bouyguestelecom.com. [176.149.143.221]) by smtp.gmail.com with ESMTPSA id x15-v6sm5618524wrt.53.2018.09.14.03.13.57 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 14 Sep 2018 03:13:57 -0700 (PDT) From: Romain Izard To: Nicolas Ferre , Alexandre Belloni , Wim Van Sebroeck , Guenter Roeck , Marcus Folkesson Cc: linux-arm-kernel@lists.infradead.org, linux-watchdog@vger.kernel.org, linux-kernel@vger.kernel.org, Romain Izard Subject: [PATCH 2/2] watchdog: sama5d4: write the mode register in two steps Date: Fri, 14 Sep 2018 12:13:39 +0200 Message-Id: <20180914101339.7382-3-romain.izard.pro@gmail.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20180914101339.7382-1-romain.izard.pro@gmail.com> References: <20180914101339.7382-1-romain.izard.pro@gmail.com> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org The specification for SAMA5D2 and SAMA5D4 chips, that use this IP for their watchdog timer, has the following advice regarding the Mode Register: "When setting the WDDIS bit, and while it is set, the fields WDV and WDD must not be modified." I have observed on a board based on a SAMA5D2 chip that using any other timeout duration than the default 16s in the device tree will reset the board when the watchdog device is opened; this is probably due to ignoring the aforementioned constraint. To fix this, read the content of the Mode Register before writing it, and split the access into two parts if WDV or WDD need to be changed. Signed-off-by: Romain Izard --- drivers/watchdog/sama5d4_wdt.c | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/drivers/watchdog/sama5d4_wdt.c b/drivers/watchdog/sama5d4_wdt.c index 1e93c1b0e3cf..1e05268ad94b 100644 --- a/drivers/watchdog/sama5d4_wdt.c +++ b/drivers/watchdog/sama5d4_wdt.c @@ -46,7 +46,10 @@ MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); -#define wdt_enabled (!(wdt->mr & AT91_WDT_WDDIS)) +#define wdt_enabled(reg) (!((reg) & AT91_WDT_WDDIS)) + +#define wdt_different_counters(reg_a, reg_b) \ + (((reg_a) ^ (reg_b)) & (AT91_WDT_WDV | AT91_WDT_WDD)) #define wdt_read(wdt, field) \ readl_relaxed((wdt)->reg_base + (field)) @@ -78,8 +81,11 @@ static void wdt_write_nosleep(struct sama5d4_wdt *wdt, u32 field, u32 val) static int sama5d4_wdt_start(struct watchdog_device *wdd) { struct sama5d4_wdt *wdt = watchdog_get_drvdata(wdd); + u32 reg = wdt_read(wdt, AT91_WDT_MR); wdt->mr &= ~AT91_WDT_WDDIS; + if (!wdt_enabled(reg) && wdt_different_counters(reg, wdt->mr)) + wdt_write(wdt, AT91_WDT_MR, reg & ~AT91_WDT_WDDIS); wdt_write(wdt, AT91_WDT_MR, wdt->mr); return 0; @@ -88,8 +94,11 @@ static int sama5d4_wdt_start(struct watchdog_device *wdd) static int sama5d4_wdt_stop(struct watchdog_device *wdd) { struct sama5d4_wdt *wdt = watchdog_get_drvdata(wdd); + u32 reg = wdt_read(wdt, AT91_WDT_MR); wdt->mr |= AT91_WDT_WDDIS; + if (wdt_enabled(reg) && wdt_different_counters(reg, wdt->mr)) + wdt_write(wdt, AT91_WDT_MR, wdt->mr & ~AT91_WDT_WDDIS); wdt_write(wdt, AT91_WDT_MR, wdt->mr); return 0; @@ -122,7 +131,7 @@ static int sama5d4_wdt_set_timeout(struct watchdog_device *wdd, * If the watchdog is enabled, then the timeout can be updated. Else, * wait that the user enables it. */ - if (wdt_enabled) + if (wdt_enabled(wdt->mr)) wdt_write(wdt, AT91_WDT_MR, wdt->mr & ~AT91_WDT_WDDIS); wdd->timeout = timeout; @@ -186,13 +195,17 @@ static int sama5d4_wdt_init(struct sama5d4_wdt *wdt) * If the watchdog is already running, we can safely update it. * Else, we have to disable it properly. */ - if (wdt_enabled) { + reg = wdt_read(wdt, AT91_WDT_MR); + if (wdt_enabled(reg)) { + if (!wdt_enabled(wdt->mr)) + wdt_write_nosleep(wdt, AT91_WDT_MR, + wdt->mr & ~AT91_WDT_WDDIS); wdt_write_nosleep(wdt, AT91_WDT_MR, wdt->mr); - } else { - reg = wdt_read(wdt, AT91_WDT_MR); - if (!(reg & AT91_WDT_WDDIS)) + } else if (wdt_enabled(wdt->mr)) { + if (wdt_different_counters(reg, wdt->mr)) wdt_write_nosleep(wdt, AT91_WDT_MR, - reg | AT91_WDT_WDDIS); + reg & ~AT91_WDT_WDDIS); + wdt_write_nosleep(wdt, AT91_WDT_MR, wdt->mr); } return 0; } -- 2.17.1