2019-06-24 03:04:21

by Sowjanya Komatineni

[permalink] [raw]
Subject: [PATCH V4 02/18] pinctrl: tegra: add suspend and resume support

This patch adds support for Tegra pinctrl driver suspend and resume.

During suspend, context of all pinctrl registers are stored and
on resume they are all restored to have all the pinmux and pad
configuration for normal operation.

Signed-off-by: Sowjanya Komatineni <[email protected]>
---
drivers/pinctrl/tegra/pinctrl-tegra.c | 47 ++++++++++++++++++++++++++++++++
drivers/pinctrl/tegra/pinctrl-tegra.h | 4 +++
drivers/pinctrl/tegra/pinctrl-tegra210.c | 6 ++++
3 files changed, 57 insertions(+)

diff --git a/drivers/pinctrl/tegra/pinctrl-tegra.c b/drivers/pinctrl/tegra/pinctrl-tegra.c
index b03c465917b8..c0ba6fa63ad1 100644
--- a/drivers/pinctrl/tegra/pinctrl-tegra.c
+++ b/drivers/pinctrl/tegra/pinctrl-tegra.c
@@ -631,6 +631,38 @@ static void tegra_pinctrl_clear_parked_bits(struct tegra_pmx *pmx)
}
}

+int __maybe_unused tegra_pinctrl_suspend(struct device *dev)
+{
+ struct tegra_pmx *pmx = dev_get_drvdata(dev);
+ u32 *backup_regs = pmx->backup_regs;
+ u32 *regs;
+ unsigned int i, j;
+
+ for (i = 0; i < pmx->nbanks; i++) {
+ regs = pmx->regs[i];
+ for (j = 0; j < pmx->reg_bank_size[i] / 4; j++)
+ *backup_regs++ = readl(regs++);
+ }
+
+ return pinctrl_force_sleep(pmx->pctl);
+}
+
+int __maybe_unused tegra_pinctrl_resume(struct device *dev)
+{
+ struct tegra_pmx *pmx = dev_get_drvdata(dev);
+ u32 *backup_regs = pmx->backup_regs;
+ u32 *regs;
+ unsigned int i, j;
+
+ for (i = 0; i < pmx->nbanks; i++) {
+ regs = pmx->regs[i];
+ for (j = 0; j < pmx->reg_bank_size[i] / 4; j++)
+ writel(*backup_regs++, regs++);
+ }
+
+ return 0;
+}
+
static bool gpio_node_has_range(const char *compatible)
{
struct device_node *np;
@@ -655,6 +687,7 @@ int tegra_pinctrl_probe(struct platform_device *pdev,
int i;
const char **group_pins;
int fn, gn, gfn;
+ unsigned long backup_regs_size = 0;

pmx = devm_kzalloc(&pdev->dev, sizeof(*pmx), GFP_KERNEL);
if (!pmx)
@@ -707,6 +740,7 @@ int tegra_pinctrl_probe(struct platform_device *pdev,
res = platform_get_resource(pdev, IORESOURCE_MEM, i);
if (!res)
break;
+ backup_regs_size += resource_size(res);
}
pmx->nbanks = i;

@@ -715,11 +749,24 @@ int tegra_pinctrl_probe(struct platform_device *pdev,
if (!pmx->regs)
return -ENOMEM;

+ pmx->reg_bank_size = devm_kcalloc(&pdev->dev, pmx->nbanks,
+ sizeof(*pmx->reg_bank_size),
+ GFP_KERNEL);
+ if (!pmx->reg_bank_size)
+ return -ENOMEM;
+
+ pmx->backup_regs = devm_kzalloc(&pdev->dev, backup_regs_size,
+ GFP_KERNEL);
+ if (!pmx->backup_regs)
+ return -ENOMEM;
+
for (i = 0; i < pmx->nbanks; i++) {
res = platform_get_resource(pdev, IORESOURCE_MEM, i);
pmx->regs[i] = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(pmx->regs[i]))
return PTR_ERR(pmx->regs[i]);
+
+ pmx->reg_bank_size[i] = resource_size(res);
}

pmx->pctl = devm_pinctrl_register(&pdev->dev, &tegra_pinctrl_desc, pmx);
diff --git a/drivers/pinctrl/tegra/pinctrl-tegra.h b/drivers/pinctrl/tegra/pinctrl-tegra.h
index 32642af3f871..65fcbf8c7579 100644
--- a/drivers/pinctrl/tegra/pinctrl-tegra.h
+++ b/drivers/pinctrl/tegra/pinctrl-tegra.h
@@ -17,6 +17,8 @@ struct tegra_pmx {

int nbanks;
void __iomem **regs;
+ size_t *reg_bank_size;
+ u32 *backup_regs;
};

enum tegra_pinconf_param {
@@ -195,4 +197,6 @@ struct tegra_pinctrl_soc_data {

int tegra_pinctrl_probe(struct platform_device *pdev,
const struct tegra_pinctrl_soc_data *soc_data);
+int __maybe_unused tegra_pinctrl_suspend(struct device *dev);
+int __maybe_unused tegra_pinctrl_resume(struct device *dev);
#endif
diff --git a/drivers/pinctrl/tegra/pinctrl-tegra210.c b/drivers/pinctrl/tegra/pinctrl-tegra210.c
index 617ad963f5ad..4616bbc2efba 100644
--- a/drivers/pinctrl/tegra/pinctrl-tegra210.c
+++ b/drivers/pinctrl/tegra/pinctrl-tegra210.c
@@ -1562,6 +1562,11 @@ static int tegra210_pinctrl_probe(struct platform_device *pdev)
return tegra_pinctrl_probe(pdev, &tegra210_pinctrl);
}

+static const struct dev_pm_ops tegra_pinctrl_pm = {
+ .suspend = &tegra_pinctrl_suspend,
+ .resume = &tegra_pinctrl_resume
+};
+
static const struct of_device_id tegra210_pinctrl_of_match[] = {
{ .compatible = "nvidia,tegra210-pinmux", },
{ },
@@ -1571,6 +1576,7 @@ static struct platform_driver tegra210_pinctrl_driver = {
.driver = {
.name = "tegra210-pinctrl",
.of_match_table = tegra210_pinctrl_of_match,
+ .pm = &tegra_pinctrl_pm,
},
.probe = tegra210_pinctrl_probe,
};
--
2.7.4


2019-06-24 09:56:55

by Dmitry Osipenko

[permalink] [raw]
Subject: Re: [PATCH V4 02/18] pinctrl: tegra: add suspend and resume support

24.06.2019 6:02, Sowjanya Komatineni пишет:
> This patch adds support for Tegra pinctrl driver suspend and resume.
>
> During suspend, context of all pinctrl registers are stored and
> on resume they are all restored to have all the pinmux and pad
> configuration for normal operation.
>
> Signed-off-by: Sowjanya Komatineni <[email protected]>
> ---
> drivers/pinctrl/tegra/pinctrl-tegra.c | 47 ++++++++++++++++++++++++++++++++
> drivers/pinctrl/tegra/pinctrl-tegra.h | 4 +++
> drivers/pinctrl/tegra/pinctrl-tegra210.c | 6 ++++
> 3 files changed, 57 insertions(+)
>
> diff --git a/drivers/pinctrl/tegra/pinctrl-tegra.c b/drivers/pinctrl/tegra/pinctrl-tegra.c
> index b03c465917b8..c0ba6fa63ad1 100644
> --- a/drivers/pinctrl/tegra/pinctrl-tegra.c
> +++ b/drivers/pinctrl/tegra/pinctrl-tegra.c
> @@ -631,6 +631,38 @@ static void tegra_pinctrl_clear_parked_bits(struct tegra_pmx *pmx)
> }
> }
>
> +int __maybe_unused tegra_pinctrl_suspend(struct device *dev)

The "maybe_unused" attribute isn't needed for global functions because
compiler always assumes that such functions are used somewhere outside.

> +{
> + struct tegra_pmx *pmx = dev_get_drvdata(dev);
> + u32 *backup_regs = pmx->backup_regs;
> + u32 *regs;
> + unsigned int i, j;
> +
> + for (i = 0; i < pmx->nbanks; i++) {
> + regs = pmx->regs[i];
> + for (j = 0; j < pmx->reg_bank_size[i] / 4; j++)
> + *backup_regs++ = readl(regs++);
> + }
> +
> + return pinctrl_force_sleep(pmx->pctl);
> +}
> +
> +int __maybe_unused tegra_pinctrl_resume(struct device *dev)
> +{
> + struct tegra_pmx *pmx = dev_get_drvdata(dev);
> + u32 *backup_regs = pmx->backup_regs;
> + u32 *regs;
> + unsigned int i, j;
> +
> + for (i = 0; i < pmx->nbanks; i++) {
> + regs = pmx->regs[i];
> + for (j = 0; j < pmx->reg_bank_size[i] / 4; j++)
> + writel(*backup_regs++, regs++);
> + }
> +
> + return 0;
> +}
> +
> static bool gpio_node_has_range(const char *compatible)
> {
> struct device_node *np;
> @@ -655,6 +687,7 @@ int tegra_pinctrl_probe(struct platform_device *pdev,
> int i;
> const char **group_pins;
> int fn, gn, gfn;
> + unsigned long backup_regs_size = 0;
>
> pmx = devm_kzalloc(&pdev->dev, sizeof(*pmx), GFP_KERNEL);
> if (!pmx)
> @@ -707,6 +740,7 @@ int tegra_pinctrl_probe(struct platform_device *pdev,
> res = platform_get_resource(pdev, IORESOURCE_MEM, i);
> if (!res)
> break;
> + backup_regs_size += resource_size(res);
> }
> pmx->nbanks = i;
>
> @@ -715,11 +749,24 @@ int tegra_pinctrl_probe(struct platform_device *pdev,
> if (!pmx->regs)
> return -ENOMEM;
>
> + pmx->reg_bank_size = devm_kcalloc(&pdev->dev, pmx->nbanks,
> + sizeof(*pmx->reg_bank_size),
> + GFP_KERNEL);
> + if (!pmx->reg_bank_size)
> + return -ENOMEM;
> +
> + pmx->backup_regs = devm_kzalloc(&pdev->dev, backup_regs_size,
> + GFP_KERNEL);
> + if (!pmx->backup_regs)
> + return -ENOMEM;
> +
> for (i = 0; i < pmx->nbanks; i++) {
> res = platform_get_resource(pdev, IORESOURCE_MEM, i);
> pmx->regs[i] = devm_ioremap_resource(&pdev->dev, res);
> if (IS_ERR(pmx->regs[i]))
> return PTR_ERR(pmx->regs[i]);
> +
> + pmx->reg_bank_size[i] = resource_size(res);
> }
>
> pmx->pctl = devm_pinctrl_register(&pdev->dev, &tegra_pinctrl_desc, pmx);
> diff --git a/drivers/pinctrl/tegra/pinctrl-tegra.h b/drivers/pinctrl/tegra/pinctrl-tegra.h
> index 32642af3f871..65fcbf8c7579 100644
> --- a/drivers/pinctrl/tegra/pinctrl-tegra.h
> +++ b/drivers/pinctrl/tegra/pinctrl-tegra.h
> @@ -17,6 +17,8 @@ struct tegra_pmx {
>
> int nbanks;
> void __iomem **regs;
> + size_t *reg_bank_size;
> + u32 *backup_regs;
> };
>
> enum tegra_pinconf_param {
> @@ -195,4 +197,6 @@ struct tegra_pinctrl_soc_data {
>
> int tegra_pinctrl_probe(struct platform_device *pdev,
> const struct tegra_pinctrl_soc_data *soc_data);
> +int __maybe_unused tegra_pinctrl_suspend(struct device *dev);
> +int __maybe_unused tegra_pinctrl_resume(struct device *dev);
> #endif
> diff --git a/drivers/pinctrl/tegra/pinctrl-tegra210.c b/drivers/pinctrl/tegra/pinctrl-tegra210.c
> index 617ad963f5ad..4616bbc2efba 100644
> --- a/drivers/pinctrl/tegra/pinctrl-tegra210.c
> +++ b/drivers/pinctrl/tegra/pinctrl-tegra210.c
> @@ -1562,6 +1562,11 @@ static int tegra210_pinctrl_probe(struct platform_device *pdev)
> return tegra_pinctrl_probe(pdev, &tegra210_pinctrl);
> }
>
> +static const struct dev_pm_ops tegra_pinctrl_pm = {
> + .suspend = &tegra_pinctrl_suspend,
> + .resume = &tegra_pinctrl_resume
> +};

What about to move tegra_pinctrl_pm out into pinctrl-tegra.c to make it
common for all of the drivers?

2019-06-24 20:53:46

by Sowjanya Komatineni

[permalink] [raw]
Subject: Re: [PATCH V4 02/18] pinctrl: tegra: add suspend and resume support


On 6/24/19 2:46 AM, Dmitry Osipenko wrote:
> 24.06.2019 6:02, Sowjanya Komatineni пишет:
>> This patch adds support for Tegra pinctrl driver suspend and resume.
>>
>> During suspend, context of all pinctrl registers are stored and
>> on resume they are all restored to have all the pinmux and pad
>> configuration for normal operation.
>>
>> Signed-off-by: Sowjanya Komatineni <[email protected]>
>> ---
>> drivers/pinctrl/tegra/pinctrl-tegra.c | 47 ++++++++++++++++++++++++++++++++
>> drivers/pinctrl/tegra/pinctrl-tegra.h | 4 +++
>> drivers/pinctrl/tegra/pinctrl-tegra210.c | 6 ++++
>> 3 files changed, 57 insertions(+)
>>
>> diff --git a/drivers/pinctrl/tegra/pinctrl-tegra.c b/drivers/pinctrl/tegra/pinctrl-tegra.c
>> index b03c465917b8..c0ba6fa63ad1 100644
>> --- a/drivers/pinctrl/tegra/pinctrl-tegra.c
>> +++ b/drivers/pinctrl/tegra/pinctrl-tegra.c
>> @@ -631,6 +631,38 @@ static void tegra_pinctrl_clear_parked_bits(struct tegra_pmx *pmx)
>> }
>> }
>>
>> +int __maybe_unused tegra_pinctrl_suspend(struct device *dev)
> The "maybe_unused" attribute isn't needed for global functions because
> compiler always assumes that such functions are used somewhere outside.
Will fix this in V5
>> +{
>> + struct tegra_pmx *pmx = dev_get_drvdata(dev);
>> + u32 *backup_regs = pmx->backup_regs;
>> + u32 *regs;
>> + unsigned int i, j;
>> +
>> + for (i = 0; i < pmx->nbanks; i++) {
>> + regs = pmx->regs[i];
>> + for (j = 0; j < pmx->reg_bank_size[i] / 4; j++)
>> + *backup_regs++ = readl(regs++);
>> + }
>> +
>> + return pinctrl_force_sleep(pmx->pctl);
>> +}
>> +
>> +int __maybe_unused tegra_pinctrl_resume(struct device *dev)
>> +{
>> + struct tegra_pmx *pmx = dev_get_drvdata(dev);
>> + u32 *backup_regs = pmx->backup_regs;
>> + u32 *regs;
>> + unsigned int i, j;
>> +
>> + for (i = 0; i < pmx->nbanks; i++) {
>> + regs = pmx->regs[i];
>> + for (j = 0; j < pmx->reg_bank_size[i] / 4; j++)
>> + writel(*backup_regs++, regs++);
>> + }
>> +
>> + return 0;
>> +}
>> +
>> static bool gpio_node_has_range(const char *compatible)
>> {
>> struct device_node *np;
>> @@ -655,6 +687,7 @@ int tegra_pinctrl_probe(struct platform_device *pdev,
>> int i;
>> const char **group_pins;
>> int fn, gn, gfn;
>> + unsigned long backup_regs_size = 0;
>>
>> pmx = devm_kzalloc(&pdev->dev, sizeof(*pmx), GFP_KERNEL);
>> if (!pmx)
>> @@ -707,6 +740,7 @@ int tegra_pinctrl_probe(struct platform_device *pdev,
>> res = platform_get_resource(pdev, IORESOURCE_MEM, i);
>> if (!res)
>> break;
>> + backup_regs_size += resource_size(res);
>> }
>> pmx->nbanks = i;
>>
>> @@ -715,11 +749,24 @@ int tegra_pinctrl_probe(struct platform_device *pdev,
>> if (!pmx->regs)
>> return -ENOMEM;
>>
>> + pmx->reg_bank_size = devm_kcalloc(&pdev->dev, pmx->nbanks,
>> + sizeof(*pmx->reg_bank_size),
>> + GFP_KERNEL);
>> + if (!pmx->reg_bank_size)
>> + return -ENOMEM;
>> +
>> + pmx->backup_regs = devm_kzalloc(&pdev->dev, backup_regs_size,
>> + GFP_KERNEL);
>> + if (!pmx->backup_regs)
>> + return -ENOMEM;
>> +
>> for (i = 0; i < pmx->nbanks; i++) {
>> res = platform_get_resource(pdev, IORESOURCE_MEM, i);
>> pmx->regs[i] = devm_ioremap_resource(&pdev->dev, res);
>> if (IS_ERR(pmx->regs[i]))
>> return PTR_ERR(pmx->regs[i]);
>> +
>> + pmx->reg_bank_size[i] = resource_size(res);
>> }
>>
>> pmx->pctl = devm_pinctrl_register(&pdev->dev, &tegra_pinctrl_desc, pmx);
>> diff --git a/drivers/pinctrl/tegra/pinctrl-tegra.h b/drivers/pinctrl/tegra/pinctrl-tegra.h
>> index 32642af3f871..65fcbf8c7579 100644
>> --- a/drivers/pinctrl/tegra/pinctrl-tegra.h
>> +++ b/drivers/pinctrl/tegra/pinctrl-tegra.h
>> @@ -17,6 +17,8 @@ struct tegra_pmx {
>>
>> int nbanks;
>> void __iomem **regs;
>> + size_t *reg_bank_size;
>> + u32 *backup_regs;
>> };
>>
>> enum tegra_pinconf_param {
>> @@ -195,4 +197,6 @@ struct tegra_pinctrl_soc_data {
>>
>> int tegra_pinctrl_probe(struct platform_device *pdev,
>> const struct tegra_pinctrl_soc_data *soc_data);
>> +int __maybe_unused tegra_pinctrl_suspend(struct device *dev);
>> +int __maybe_unused tegra_pinctrl_resume(struct device *dev);
>> #endif
>> diff --git a/drivers/pinctrl/tegra/pinctrl-tegra210.c b/drivers/pinctrl/tegra/pinctrl-tegra210.c
>> index 617ad963f5ad..4616bbc2efba 100644
>> --- a/drivers/pinctrl/tegra/pinctrl-tegra210.c
>> +++ b/drivers/pinctrl/tegra/pinctrl-tegra210.c
>> @@ -1562,6 +1562,11 @@ static int tegra210_pinctrl_probe(struct platform_device *pdev)
>> return tegra_pinctrl_probe(pdev, &tegra210_pinctrl);
>> }
>>
>> +static const struct dev_pm_ops tegra_pinctrl_pm = {
>> + .suspend = &tegra_pinctrl_suspend,
>> + .resume = &tegra_pinctrl_resume
>> +};
> What about to move tegra_pinctrl_pm out into pinctrl-tegra.c to make it
> common for all of the drivers?
OK, Will do that in V5

2019-06-26 10:10:46

by Thierry Reding

[permalink] [raw]
Subject: Re: [PATCH V4 02/18] pinctrl: tegra: add suspend and resume support

On Sun, Jun 23, 2019 at 08:02:43PM -0700, Sowjanya Komatineni wrote:
> This patch adds support for Tegra pinctrl driver suspend and resume.
>
> During suspend, context of all pinctrl registers are stored and
> on resume they are all restored to have all the pinmux and pad
> configuration for normal operation.
>
> Signed-off-by: Sowjanya Komatineni <[email protected]>
> ---
> drivers/pinctrl/tegra/pinctrl-tegra.c | 47 ++++++++++++++++++++++++++++++++
> drivers/pinctrl/tegra/pinctrl-tegra.h | 4 +++
> drivers/pinctrl/tegra/pinctrl-tegra210.c | 6 ++++
> 3 files changed, 57 insertions(+)

With Dmitry's comments addressed, this is:

Acked-by: Thierry Reding <[email protected]>


Attachments:
(No filename) (717.00 B)
signature.asc (849.00 B)
Download all attachments