STARFIVE JH71X0 PINCTRL DRIVERS
 M:     Emil Renner Berthing <kernel@esmil.dk>
 M:     Jianlong Huang <jianlong.huang@starfivetech.com>
+M:     Hal Feng <hal.feng@starfivetech.com>
 L:     linux-gpio@vger.kernel.org
 S:     Maintained
 F:     Documentation/devicetree/bindings/pinctrl/starfive,jh71*.yaml
 
 #define JH7110_AON_NGPIO               4
 #define JH7110_AON_GC_BASE             64
 
+#define JH7110_AON_REGS_NUM            37
+
 /* registers */
 #define JH7110_AON_DOEN                        0x0
 #define JH7110_AON_DOUT                        0x4
        .gpi_mask       = GENMASK(3, 0),
        .gpioin_reg_base           = JH7110_AON_GPIOIN,
        .irq_reg                   = &jh7110_aon_irq_reg,
+       .nsaved_regs               = JH7110_AON_REGS_NUM,
        .jh7110_set_one_pin_mux  = jh7110_aon_set_one_pin_mux,
        .jh7110_get_padcfg_base  = jh7110_aon_get_padcfg_base,
        .jh7110_gpio_irq_handler = jh7110_aon_irq_handler,
        .driver = {
                .name = "starfive-jh7110-aon-pinctrl",
                .of_match_table = jh7110_aon_pinctrl_of_match,
+               .pm = pm_sleep_ptr(&jh7110_pinctrl_pm_ops),
        },
 };
 module_platform_driver(jh7110_aon_pinctrl_driver);
 
 #define JH7110_SYS_NGPIO               64
 #define JH7110_SYS_GC_BASE             0
 
+#define JH7110_SYS_REGS_NUM            174
+
 /* registers */
 #define JH7110_SYS_DOEN                        0x000
 #define JH7110_SYS_DOUT                        0x040
        .gpi_mask       = GENMASK(6, 0),
        .gpioin_reg_base           = JH7110_SYS_GPIOIN,
        .irq_reg                   = &jh7110_sys_irq_reg,
+       .nsaved_regs               = JH7110_SYS_REGS_NUM,
        .jh7110_set_one_pin_mux  = jh7110_sys_set_one_pin_mux,
        .jh7110_get_padcfg_base  = jh7110_sys_get_padcfg_base,
        .jh7110_gpio_irq_handler = jh7110_sys_irq_handler,
        .driver = {
                .name = "starfive-jh7110-sys-pinctrl",
                .of_match_table = jh7110_sys_pinctrl_of_match,
+               .pm = pm_sleep_ptr(&jh7110_pinctrl_pm_ops),
        },
 };
 module_platform_driver(jh7110_sys_pinctrl_driver);
 
        if (!sfp)
                return -ENOMEM;
 
+#if IS_ENABLED(CONFIG_PM_SLEEP)
+       sfp->saved_regs = devm_kcalloc(dev, info->nsaved_regs,
+                                      sizeof(*sfp->saved_regs), GFP_KERNEL);
+       if (!sfp->saved_regs)
+               return -ENOMEM;
+#endif
+
        sfp->base = devm_platform_ioremap_resource(pdev, 0);
        if (IS_ERR(sfp->base))
                return PTR_ERR(sfp->base);
 }
 EXPORT_SYMBOL_GPL(jh7110_pinctrl_probe);
 
+static int jh7110_pinctrl_suspend(struct device *dev)
+{
+       struct jh7110_pinctrl *sfp = dev_get_drvdata(dev);
+       unsigned long flags;
+       unsigned int i;
+
+       raw_spin_lock_irqsave(&sfp->lock, flags);
+       for (i = 0 ; i < sfp->info->nsaved_regs ; i++)
+               sfp->saved_regs[i] = readl_relaxed(sfp->base + 4 * i);
+
+       raw_spin_unlock_irqrestore(&sfp->lock, flags);
+       return 0;
+}
+
+static int jh7110_pinctrl_resume(struct device *dev)
+{
+       struct jh7110_pinctrl *sfp = dev_get_drvdata(dev);
+       unsigned long flags;
+       unsigned int i;
+
+       raw_spin_lock_irqsave(&sfp->lock, flags);
+       for (i = 0 ; i < sfp->info->nsaved_regs ; i++)
+               writel_relaxed(sfp->saved_regs[i], sfp->base + 4 * i);
+
+       raw_spin_unlock_irqrestore(&sfp->lock, flags);
+       return 0;
+}
+
+const struct dev_pm_ops jh7110_pinctrl_pm_ops = {
+       LATE_SYSTEM_SLEEP_PM_OPS(jh7110_pinctrl_suspend, jh7110_pinctrl_resume)
+};
+EXPORT_SYMBOL_GPL(jh7110_pinctrl_pm_ops);
+
 MODULE_DESCRIPTION("Pinctrl driver for the StarFive JH7110 SoC");
 MODULE_AUTHOR("Emil Renner Berthing <kernel@esmil.dk>");
 MODULE_AUTHOR("Jianlong Huang <jianlong.huang@starfivetech.com>");
 
        /* register read/write mutex */
        struct mutex mutex;
        const struct jh7110_pinctrl_soc_info *info;
+       u32 *saved_regs;
 };
 
 struct jh7110_gpio_irq_reg {
 
        const struct jh7110_gpio_irq_reg *irq_reg;
 
+       unsigned int nsaved_regs;
+
        /* generic pinmux */
        int (*jh7110_set_one_pin_mux)(struct jh7110_pinctrl *sfp,
                                      unsigned int pin,
                        unsigned int din, u32 dout, u32 doen);
 int jh7110_pinctrl_probe(struct platform_device *pdev);
 struct jh7110_pinctrl *jh7110_from_irq_desc(struct irq_desc *desc);
+extern const struct dev_pm_ops jh7110_pinctrl_pm_ops;
 
 #endif /* __PINCTRL_STARFIVE_JH7110_H__ */