From patchwork Sun Dec 2 19:35:53 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marek Vasut X-Patchwork-Id: 1006546 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-gpio-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="G6gbb4ps"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 437JKB4X8Rz9s47 for ; Mon, 3 Dec 2018 06:36:30 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1725810AbeLBTgd (ORCPT ); Sun, 2 Dec 2018 14:36:33 -0500 Received: from mail-wm1-f68.google.com ([209.85.128.68]:40090 "EHLO mail-wm1-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725616AbeLBTgd (ORCPT ); Sun, 2 Dec 2018 14:36:33 -0500 Received: by mail-wm1-f68.google.com with SMTP id q26so3583454wmf.5; Sun, 02 Dec 2018 11:36:28 -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; bh=fjwrSxUeoVDo3A1Y98n1euA4k8u+X/NSJARYqIUm6JI=; b=G6gbb4psXOPo3+B1We7xjLnOJWNv705Fjv0K0I+bGrvzkMS0b3LCBe02a980544fBQ NU9LrhrHbD6afCLXn2+Wdzg4XGF6ua0dhvGtPrYm+J9CB+5vJDit69s+s+ij2yCm3yZ2 MDCS7CVd7f2dD3u0DtusWB0ElOdjr11a3YstXskodWsMfM+DtN/8mFx/8J8MpU/R7A+N YYBIpNdJ742UE1HLgpjpd+KILRBlmfIYJvjlfO/LfubUYLwlbPlu34u42a3gVQhMeHnG dC9Mmmhtc2hFGeMDlaZ+AsC5eMOo5q1d55OspvEdTd9fZwLssSirWnlbkR9riQRA415F qSNA== 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=fjwrSxUeoVDo3A1Y98n1euA4k8u+X/NSJARYqIUm6JI=; b=by067R6b5MaX6HaVCef58rxBRpBm2Fz7r1SLuvfNxwHqW/ztJiFEFDZENlDxSxqoWa vkkRSvWf4JsI4FHbUFfPoceW3hN9ooBhLDTQFxO839he/63NuycbBm4H9FigCc1tFY64 UL3aLChbWjJaEP6pzPlQzN/B2Zl1W4DFMTwqmWY+2YWFdK6+SJBQCiGxEg9zaxwtYah1 xQLuy0OBjYQoT0ZleoUM+xz+r7bCb9UmSjH8j1zO2qxv9K9+SRS1vLu/Oc2E2X7Y75dC BXjPxoQeT5WQqI/6ZseCMhhHJzvTsXU6oFNZyh4tdP1y5YJUI3vK3yktmNhHHL87zNKs 9VXQ== X-Gm-Message-State: AA+aEWY2HbHmQx7SVRMaKi7qCGCkeGCP5rDui7sWWyL7YJsVIJhS4jkK CG8c3DHBrVsENOIs7SrCZ5Hkoiml X-Google-Smtp-Source: AFSGD/XdUngfS+L8Y3Gnb5AWt3RORnzFdUR7BSURnL95DK7V2CH/NLbUN5MqOAB3nfr2ZFvKdTUAaA== X-Received: by 2002:a1c:650b:: with SMTP id z11mr5830760wmb.23.1543779387470; Sun, 02 Dec 2018 11:36:27 -0800 (PST) Received: from kurokawa.lan (ip-86-49-110-70.net.upcbroadband.cz. [86.49.110.70]) by smtp.gmail.com with ESMTPSA id y185sm4016628wmg.34.2018.12.02.11.36.26 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sun, 02 Dec 2018 11:36:26 -0800 (PST) From: Marek Vasut X-Google-Original-From: Marek Vasut To: linux-gpio@vger.kernel.org Cc: linux-renesas-soc@vger.kernel.org, Marek Vasut , Linus Walleij , Bartosz Golaszewski Subject: [PATCH 14/14] gpio: pca953x: Restore registers after suspend/resume cycle Date: Sun, 2 Dec 2018 20:35:53 +0100 Message-Id: <20181202193553.29704-14-marek.vasut+renesas@gmail.com> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20181202193553.29704-1-marek.vasut+renesas@gmail.com> References: <20181202193553.29704-1-marek.vasut+renesas@gmail.com> Sender: linux-gpio-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-gpio@vger.kernel.org It is possible that the PCA953x is powered down during suspend. Use regmap cache to assure the registers in the PCA953x are in line with the driver state after resume. Signed-off-by: Marek Vasut Cc: Linus Walleij Cc: Bartosz Golaszewski --- drivers/gpio/gpio-pca953x.c | 92 +++++++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c index 7c0122fac383..e2c2e97b7321 100644 --- a/drivers/gpio/gpio-pca953x.c +++ b/drivers/gpio/gpio-pca953x.c @@ -972,6 +972,95 @@ static int pca953x_remove(struct i2c_client *client) return ret; } +#ifdef CONFIG_PM_SLEEP +static int pca953x_regcache_sync(struct device *dev) +{ + struct pca953x_chip *chip = dev_get_drvdata(dev); + int ret; + + /* + * The ordering between direction and output is important, + * sync these registers first and only then sync the rest. + */ + ret = regcache_sync_region(chip->regmap, chip->regs->direction, + chip->regs->direction + NBANK(chip)); + if (ret != 0) { + dev_err(dev, "Failed to sync GPIO dir registers: %d\n", ret); + return ret; + } + + ret = regcache_sync_region(chip->regmap, chip->regs->output, + chip->regs->output + NBANK(chip)); + if (ret != 0) { + dev_err(dev, "Failed to sync GPIO out registers: %d\n", ret); + return ret; + } + +#ifdef CONFIG_GPIO_PCA953X_IRQ + if (chip->driver_data & PCA_PCAL) { + pca953x_write_regs(chip, PCAL953X_IN_LATCH, chip->irq_mask); + pca953x_write_regs(chip, PCAL953X_INT_MASK, invert_irq_mask); + + ret = regcache_sync_region(chip->regmap, PCAL953X_IN_LATCH, + PCAL953X_IN_LATCH + NBANK(chip)); + if (ret != 0) { + dev_err(dev, "Failed to sync INT latch registers: %d\n", + ret); + return ret; + } + + ret = regcache_sync_region(chip->regmap, PCAL953X_INT_MASK, + PCAL953X_INT_MASK + NBANK(chip)); + if (ret != 0) { + dev_err(dev, "Failed to sync INT mask registers: %d\n", + ret); + return ret; + } + } +#endif + + return 0; +} + +static int pca953x_suspend(struct device *dev) +{ + struct pca953x_chip *chip = dev_get_drvdata(dev); + + regcache_mark_dirty(chip->regmap); + pca953x_regcache_sync(dev); + regcache_cache_only(chip->regmap, true); + + regulator_disable(chip->regulator); + + return 0; +} + +static int pca953x_resume(struct device *dev) +{ + struct pca953x_chip *chip = dev_get_drvdata(dev); + int ret; + + ret = regulator_enable(chip->regulator); + if (ret != 0) { + dev_err(dev, "Failed to enable regulator: %d\n", ret); + return 0; + } + + regcache_cache_only(chip->regmap, false); + ret = pca953x_regcache_sync(dev); + if (ret) + return ret; + + ret = regcache_sync(chip->regmap); + if (ret != 0) { + dev_err(dev, "Failed to restore register map: %d\n", ret); + return ret; + } + + return 0; +} +#endif + /* convenience to stop overlong match-table lines */ #define OF_953X(__nrgpio, __int) (void *)(__nrgpio | PCA953X_TYPE | __int) #define OF_957X(__nrgpio, __int) (void *)(__nrgpio | PCA957X_TYPE | __int) @@ -1015,9 +1104,12 @@ static const struct of_device_id pca953x_dt_ids[] = { MODULE_DEVICE_TABLE(of, pca953x_dt_ids); +static SIMPLE_DEV_PM_OPS(pca953x_pm_ops, pca953x_suspend, pca953x_resume); + static struct i2c_driver pca953x_driver = { .driver = { .name = "pca953x", + .pm = &pca953x_pm_ops, .of_match_table = pca953x_dt_ids, .acpi_match_table = ACPI_PTR(pca953x_acpi_ids), },