From patchwork Mon Jul 31 06:21:10 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Masahiro Yamada X-Patchwork-Id: 108972 Delivered-To: patch@linaro.org Received: by 10.140.101.44 with SMTP id t41csp1915621qge; Sun, 30 Jul 2017 23:23:30 -0700 (PDT) X-Received: by 10.84.209.204 with SMTP id y70mr16505776plh.44.1501482210145; Sun, 30 Jul 2017 23:23:30 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1501482210; cv=none; d=google.com; s=arc-20160816; b=fxZf9ye++rGa0vaPB8Rhl3POJ1eTjfpXb2iO6GwFnIlNdKht0o8JEKkrqtGU0EkCvk XQENYQ3xNzezaEFjYaAlfT5X6aqI3RQfofuNSlqS3jGURW5/IJW6lo2ZspGo4cQVhJgb Oabp0YA/hKm4DGO1ripbm3ql2IDvZreRkdHP4T0kHwuCuzn70hpWUydlbackqeXr8WaG C1CSUvUKFZqWoYPVKnMRPmBhCnaHxFjOjpEJEkZFcL+ieNdC3iSO5cZZr81+06WXe6v1 4M4RIfJEi8f4svIl9MLby9jv8GMKLftR5wzaFxgxezvxQLnLDgZ0vzUjvf86JN4q6uOY LeFA== 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:dkim-filter :arc-authentication-results; bh=rH+SmCsramvkgPtSBmBbhnWnYn4L+DA3Q9BRCDOErmQ=; b=Oc85Jp/sRE10xEt+cGJub7bN3eZ8/7J+DImAFjLNo1xAAN42MYBGKfI7JToV2qgzhO IcrGouc98zOUxnPIhkEhJZqXGw7Ic9WAtN7eMqzOsByci/FOv1W0DprJeEkiIIPLGoi5 2grCXxo0JvbqsZZn7TUGEWUKLPKkCDCOaxOW5HRtHwO2a1pgQYVIs05xd3jyneCcLk32 s6Sijkw8PPpqqpc8cHmzAs2E1sqPfSKYXteO3+o9l0euolPNpZmO9o5QDItrvdLnyK42 8ACwFFP2MEy3swJ5a5xm1gqTxxY+7mpF1xCsenDhAq//Ep77M5f6skylJzEsatECev49 eb7A== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@nifty.com header.b=ZemSY4eI; 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 Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id 128si851976pgc.16.2017.07.30.23.23.29; Sun, 30 Jul 2017 23:23:30 -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=@nifty.com header.b=ZemSY4eI; 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 Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751790AbdGaGXW (ORCPT + 26 others); Mon, 31 Jul 2017 02:23:22 -0400 Received: from conuserg-10.nifty.com ([210.131.2.77]:41405 "EHLO conuserg-10.nifty.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751199AbdGaGXI (ORCPT ); Mon, 31 Jul 2017 02:23:08 -0400 Received: from pug.e01.socionext.com (p14092-ipngnfx01kyoto.kyoto.ocn.ne.jp [153.142.97.92]) (authenticated) by conuserg-10.nifty.com with ESMTP id v6V6M3A6000955; Mon, 31 Jul 2017 15:22:09 +0900 DKIM-Filter: OpenDKIM Filter v2.10.3 conuserg-10.nifty.com v6V6M3A6000955 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nifty.com; s=dec2015msa; t=1501482129; bh=rH+SmCsramvkgPtSBmBbhnWnYn4L+DA3Q9BRCDOErmQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=ZemSY4eIT1W3yMoyhR2RlkHb5hcDNNIZ1qBGLWmkFMQ0j7mH5MODTbyCa1aBe7VUF 8PXu9Rur1HXQqqCPEoDttrQZugRTpEbaH+rR98K4wNnfab4Uh+ep/ysWneobLJKW5U CN5GEvoSAat9e5UzAcK8OiYqAWfHj7tH4sd3s78RG2pY+n4o9QvQXvH+JLmJUTGd08 blsr1Wyk+WqiGyYqVxF/DK0PI+I3+w2xhPNd4riEmNgZFN9uT2B/B75r7J/0nYdK8a /wyz7NdnwG7a/KHZPHaun17Rj5yjZlFNCzBfppG7j/GSXfto45OqQTtAjHy0NRvAI/ DpZkySziQ7s8Q== X-Nifty-SrcIP: [153.142.97.92] From: Masahiro Yamada To: linux-gpio@vger.kernel.org Cc: Masahiro Yamada , Linus Walleij , linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org Subject: [PATCH 5/6] pinctrl: uniphier: add suspend / resume support Date: Mon, 31 Jul 2017 15:21:10 +0900 Message-Id: <1501482071-9819-6-git-send-email-yamada.masahiro@socionext.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1501482071-9819-1-git-send-email-yamada.masahiro@socionext.com> References: <1501482071-9819-1-git-send-email-yamada.masahiro@socionext.com> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Save registers lost in the sleep when suspending, and restore them when resuming. Signed-off-by: Masahiro Yamada --- drivers/pinctrl/uniphier/pinctrl-uniphier-core.c | 178 +++++++++++++++++++++++ drivers/pinctrl/uniphier/pinctrl-uniphier-ld11.c | 1 + drivers/pinctrl/uniphier/pinctrl-uniphier-ld20.c | 1 + drivers/pinctrl/uniphier/pinctrl-uniphier-ld4.c | 1 + drivers/pinctrl/uniphier/pinctrl-uniphier-ld6b.c | 1 + drivers/pinctrl/uniphier/pinctrl-uniphier-pro4.c | 1 + drivers/pinctrl/uniphier/pinctrl-uniphier-pro5.c | 1 + drivers/pinctrl/uniphier/pinctrl-uniphier-pxs2.c | 1 + drivers/pinctrl/uniphier/pinctrl-uniphier-sld8.c | 1 + drivers/pinctrl/uniphier/pinctrl-uniphier.h | 2 + 10 files changed, 188 insertions(+) -- 2.7.4 diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c index b976e9109b1d..5d8c9efd8135 100644 --- a/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c +++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c @@ -13,6 +13,7 @@ * GNU General Public License for more details. */ +#include #include #include #include @@ -34,11 +35,19 @@ #define UNIPHIER_PINCTRL_PUPDCTRL_BASE 0x1a00 #define UNIPHIER_PINCTRL_IECTRL_BASE 0x1d00 +struct uniphier_pinctrl_reg_region { + struct list_head node; + unsigned int base; + unsigned int nregs; + u32 vals[0]; +}; + struct uniphier_pinctrl_priv { struct pinctrl_desc pctldesc; struct pinctrl_dev *pctldev; struct regmap *regmap; struct uniphier_pinctrl_socdata *socdata; + struct list_head reg_regions; }; static int uniphier_pctl_get_groups_count(struct pinctrl_dev *pctldev) @@ -688,12 +697,177 @@ static const struct pinmux_ops uniphier_pmxops = { .strict = true, }; +#ifdef CONFIG_PM_SLEEP +static int uniphier_pinctrl_suspend(struct device *dev) +{ + struct uniphier_pinctrl_priv *priv = dev_get_drvdata(dev); + struct uniphier_pinctrl_reg_region *r; + int ret; + + list_for_each_entry(r, &priv->reg_regions, node) { + ret = regmap_bulk_read(priv->regmap, r->base, r->vals, + r->nregs); + if (ret) + return ret; + } + + return 0; +} + +static int uniphier_pinctrl_resume(struct device *dev) +{ + struct uniphier_pinctrl_priv *priv = dev_get_drvdata(dev); + struct uniphier_pinctrl_reg_region *r; + int ret; + + list_for_each_entry(r, &priv->reg_regions, node) { + ret = regmap_bulk_write(priv->regmap, r->base, r->vals, + r->nregs); + if (ret) + return ret; + } + + if (priv->socdata->caps & UNIPHIER_PINCTRL_CAPS_DBGMUX_SEPARATE) { + ret = regmap_write(priv->regmap, + UNIPHIER_PINCTRL_LOAD_PINMUX, 1); + if (ret) + return ret; + } + + return 0; +} + +static int uniphier_pinctrl_add_reg_region(struct device *dev, + struct uniphier_pinctrl_priv *priv, + unsigned int base, + unsigned int count, + unsigned int width) +{ + struct uniphier_pinctrl_reg_region *region; + unsigned int nregs; + + if (!count) + return 0; + + nregs = DIV_ROUND_UP(count * width, 32); + + region = devm_kzalloc(dev, + sizeof(*region) + sizeof(region->vals[0]) * nregs, + GFP_KERNEL); + if (!region) + return -ENOMEM; + + region->base = base; + region->nregs = nregs; + + list_add_tail(®ion->node, &priv->reg_regions); + + return 0; +} +#endif + +static int uniphier_pinctrl_pm_init(struct device *dev, + struct uniphier_pinctrl_priv *priv) +{ +#ifdef CONFIG_PM_SLEEP + const struct uniphier_pinctrl_socdata *socdata = priv->socdata; + unsigned int num_drvctrl = 0; + unsigned int num_drv2ctrl = 0; + unsigned int num_drv3ctrl = 0; + unsigned int num_pupdctrl = 0; + unsigned int num_iectrl = 0; + unsigned int iectrl, drvctrl, pupdctrl; + enum uniphier_pin_drv_type drv_type; + enum uniphier_pin_pull_dir pull_dir; + int i, ret; + + for (i = 0; i < socdata->npins; i++) { + void *drv_data = socdata->pins[i].drv_data; + + drvctrl = uniphier_pin_get_drvctrl(drv_data); + drv_type = uniphier_pin_get_drv_type(drv_data); + pupdctrl = uniphier_pin_get_pupdctrl(drv_data); + pull_dir = uniphier_pin_get_pull_dir(drv_data); + iectrl = uniphier_pin_get_iectrl(drv_data); + + switch (drv_type) { + case UNIPHIER_PIN_DRV_1BIT: + num_drvctrl = max(num_drvctrl, drvctrl + 1); + break; + case UNIPHIER_PIN_DRV_2BIT: + num_drv2ctrl = max(num_drv2ctrl, drvctrl + 1); + break; + case UNIPHIER_PIN_DRV_3BIT: + num_drv3ctrl = max(num_drv3ctrl, drvctrl + 1); + break; + default: + break; + } + + if (pull_dir == UNIPHIER_PIN_PULL_UP || + pull_dir == UNIPHIER_PIN_PULL_DOWN) + num_pupdctrl = max(num_pupdctrl, pupdctrl + 1); + + if (iectrl != UNIPHIER_PIN_IECTRL_NONE) { + if (socdata->caps & UNIPHIER_PINCTRL_CAPS_PERPIN_IECTRL) + iectrl = i; + num_iectrl = max(num_iectrl, iectrl + 1); + } + } + + INIT_LIST_HEAD(&priv->reg_regions); + + ret = uniphier_pinctrl_add_reg_region(dev, priv, + UNIPHIER_PINCTRL_PINMUX_BASE, + socdata->npins, 8); + if (ret) + return ret; + + ret = uniphier_pinctrl_add_reg_region(dev, priv, + UNIPHIER_PINCTRL_DRVCTRL_BASE, + num_drvctrl, 1); + if (ret) + return ret; + + ret = uniphier_pinctrl_add_reg_region(dev, priv, + UNIPHIER_PINCTRL_DRV2CTRL_BASE, + num_drv2ctrl, 2); + if (ret) + return ret; + + ret = uniphier_pinctrl_add_reg_region(dev, priv, + UNIPHIER_PINCTRL_DRV3CTRL_BASE, + num_drv3ctrl, 3); + if (ret) + return ret; + + ret = uniphier_pinctrl_add_reg_region(dev, priv, + UNIPHIER_PINCTRL_PUPDCTRL_BASE, + num_pupdctrl, 1); + if (ret) + return ret; + + ret = uniphier_pinctrl_add_reg_region(dev, priv, + UNIPHIER_PINCTRL_IECTRL_BASE, + num_iectrl, 1); + if (ret) + return ret; +#endif + return 0; +} + +const struct dev_pm_ops uniphier_pinctrl_pm_ops = { + SET_LATE_SYSTEM_SLEEP_PM_OPS(uniphier_pinctrl_suspend, + uniphier_pinctrl_resume) +}; + int uniphier_pinctrl_probe(struct platform_device *pdev, struct uniphier_pinctrl_socdata *socdata) { struct device *dev = &pdev->dev; struct uniphier_pinctrl_priv *priv; struct device_node *parent; + int ret; if (!socdata || !socdata->pins || !socdata->npins || @@ -725,6 +899,10 @@ int uniphier_pinctrl_probe(struct platform_device *pdev, priv->pctldesc.confops = &uniphier_confops; priv->pctldesc.owner = dev->driver->owner; + ret = uniphier_pinctrl_pm_init(dev, priv); + if (ret) + return ret; + priv->pctldev = devm_pinctrl_register(dev, &priv->pctldesc, priv); if (IS_ERR(priv->pctldev)) { dev_err(dev, "failed to register UniPhier pinctrl driver\n"); diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-ld11.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-ld11.c index be08de07146e..745706920642 100644 --- a/drivers/pinctrl/uniphier/pinctrl-uniphier-ld11.c +++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-ld11.c @@ -643,6 +643,7 @@ static struct platform_driver uniphier_ld11_pinctrl_driver = { .driver = { .name = "uniphier-ld11-pinctrl", .of_match_table = uniphier_ld11_pinctrl_match, + .pm = &uniphier_pinctrl_pm_ops, }, }; builtin_platform_driver(uniphier_ld11_pinctrl_driver); diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-ld20.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-ld20.c index e5bc7c36c1e4..82f754cd85d9 100644 --- a/drivers/pinctrl/uniphier/pinctrl-uniphier-ld20.c +++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-ld20.c @@ -733,6 +733,7 @@ static struct platform_driver uniphier_ld20_pinctrl_driver = { .driver = { .name = "uniphier-ld20-pinctrl", .of_match_table = uniphier_ld20_pinctrl_match, + .pm = &uniphier_pinctrl_pm_ops, }, }; builtin_platform_driver(uniphier_ld20_pinctrl_driver); diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-ld4.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-ld4.c index 7db3fd0f72e5..840382847212 100644 --- a/drivers/pinctrl/uniphier/pinctrl-uniphier-ld4.c +++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-ld4.c @@ -740,6 +740,7 @@ static struct platform_driver uniphier_ld4_pinctrl_driver = { .driver = { .name = "uniphier-ld4-pinctrl", .of_match_table = uniphier_ld4_pinctrl_match, + .pm = &uniphier_pinctrl_pm_ops, }, }; builtin_platform_driver(uniphier_ld4_pinctrl_driver); diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-ld6b.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-ld6b.c index 2d8dc0f0b907..493a90c6d733 100644 --- a/drivers/pinctrl/uniphier/pinctrl-uniphier-ld6b.c +++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-ld6b.c @@ -950,6 +950,7 @@ static struct platform_driver uniphier_ld6b_pinctrl_driver = { .driver = { .name = "uniphier-ld6b-pinctrl", .of_match_table = uniphier_ld6b_pinctrl_match, + .pm = &uniphier_pinctrl_pm_ops, }, }; builtin_platform_driver(uniphier_ld6b_pinctrl_driver); diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-pro4.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-pro4.c index 1c95a4689eda..24d358290a0c 100644 --- a/drivers/pinctrl/uniphier/pinctrl-uniphier-pro4.c +++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-pro4.c @@ -1245,6 +1245,7 @@ static struct platform_driver uniphier_pro4_pinctrl_driver = { .driver = { .name = "uniphier-pro4-pinctrl", .of_match_table = uniphier_pro4_pinctrl_match, + .pm = &uniphier_pinctrl_pm_ops, }, }; builtin_platform_driver(uniphier_pro4_pinctrl_driver); diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-pro5.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-pro5.c index d0d730b2e71e..9381a4ff4389 100644 --- a/drivers/pinctrl/uniphier/pinctrl-uniphier-pro5.c +++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-pro5.c @@ -1003,6 +1003,7 @@ static struct platform_driver uniphier_pro5_pinctrl_driver = { .driver = { .name = "uniphier-pro5-pinctrl", .of_match_table = uniphier_pro5_pinctrl_match, + .pm = &uniphier_pinctrl_pm_ops, }, }; builtin_platform_driver(uniphier_pro5_pinctrl_driver); diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-pxs2.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-pxs2.c index e323c3e19a41..c0ef40ae99a7 100644 --- a/drivers/pinctrl/uniphier/pinctrl-uniphier-pxs2.c +++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-pxs2.c @@ -937,6 +937,7 @@ static struct platform_driver uniphier_pxs2_pinctrl_driver = { .driver = { .name = "uniphier-pxs2-pinctrl", .of_match_table = uniphier_pxs2_pinctrl_match, + .pm = &uniphier_pinctrl_pm_ops, }, }; builtin_platform_driver(uniphier_pxs2_pinctrl_driver); diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-sld8.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-sld8.c index f0221e93aa25..1af430d701be 100644 --- a/drivers/pinctrl/uniphier/pinctrl-uniphier-sld8.c +++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-sld8.c @@ -669,6 +669,7 @@ static struct platform_driver uniphier_sld8_pinctrl_driver = { .driver = { .name = "uniphier-sld8-pinctrl", .of_match_table = uniphier_sld8_pinctrl_match, + .pm = &uniphier_pinctrl_pm_ops, }, }; builtin_platform_driver(uniphier_sld8_pinctrl_driver); diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier.h b/drivers/pinctrl/uniphier/pinctrl-uniphier.h index 24e48e3ed048..c075ecb8e5db 100644 --- a/drivers/pinctrl/uniphier/pinctrl-uniphier.h +++ b/drivers/pinctrl/uniphier/pinctrl-uniphier.h @@ -192,4 +192,6 @@ struct uniphier_pinctrl_socdata { int uniphier_pinctrl_probe(struct platform_device *pdev, struct uniphier_pinctrl_socdata *socdata); +extern const struct dev_pm_ops uniphier_pinctrl_pm_ops; + #endif /* __PINCTRL_UNIPHIER_H__ */