From 716ca530e1c4515d8683c9d5be3d56b301758b66 Mon Sep 17 00:00:00 2001 From: James <> Date: Wed, 4 Nov 2015 11:49:21 +0000 Subject: trunk-47381 --- .../patches-3.18/198-gpio_mvebu_suspend.patch | 137 +++++++++++++++++++++ 1 file changed, 137 insertions(+) create mode 100644 target/linux/mvebu/patches-3.18/198-gpio_mvebu_suspend.patch (limited to 'target/linux/mvebu/patches-3.18/198-gpio_mvebu_suspend.patch') diff --git a/target/linux/mvebu/patches-3.18/198-gpio_mvebu_suspend.patch b/target/linux/mvebu/patches-3.18/198-gpio_mvebu_suspend.patch new file mode 100644 index 0000000..9ef1815 --- /dev/null +++ b/target/linux/mvebu/patches-3.18/198-gpio_mvebu_suspend.patch @@ -0,0 +1,137 @@ +This commit adds the implementation of ->suspend() and ->resume() +platform_driver hooks in order to save and restore the state of the +GPIO configuration. In order to achieve that, additional fields are +added to the mvebu_gpio_chip structure. + +Signed-off-by: Thomas Petazzoni +Acked-by: Alexandre Courbot +Signed-off-by: Linus Walleij + +--- a/drivers/gpio/gpio-mvebu.c ++++ b/drivers/gpio/gpio-mvebu.c +@@ -83,6 +83,14 @@ struct mvebu_gpio_chip { + int irqbase; + struct irq_domain *domain; + int soc_variant; ++ ++ /* Used to preserve GPIO registers accross suspend/resume */ ++ u32 out_reg; ++ u32 io_conf_reg; ++ u32 blink_en_reg; ++ u32 in_pol_reg; ++ u32 edge_mask_regs[4]; ++ u32 level_mask_regs[4]; + }; + + /* +@@ -562,6 +570,93 @@ static const struct of_device_id mvebu_g + }; + MODULE_DEVICE_TABLE(of, mvebu_gpio_of_match); + ++static int mvebu_gpio_suspend(struct platform_device *pdev, pm_message_t state) ++{ ++ struct mvebu_gpio_chip *mvchip = platform_get_drvdata(pdev); ++ int i; ++ ++ mvchip->out_reg = readl(mvebu_gpioreg_out(mvchip)); ++ mvchip->io_conf_reg = readl(mvebu_gpioreg_io_conf(mvchip)); ++ mvchip->blink_en_reg = readl(mvebu_gpioreg_blink(mvchip)); ++ mvchip->in_pol_reg = readl(mvebu_gpioreg_in_pol(mvchip)); ++ ++ switch (mvchip->soc_variant) { ++ case MVEBU_GPIO_SOC_VARIANT_ORION: ++ mvchip->edge_mask_regs[0] = ++ readl(mvchip->membase + GPIO_EDGE_MASK_OFF); ++ mvchip->level_mask_regs[0] = ++ readl(mvchip->membase + GPIO_LEVEL_MASK_OFF); ++ break; ++ case MVEBU_GPIO_SOC_VARIANT_MV78200: ++ for (i = 0; i < 2; i++) { ++ mvchip->edge_mask_regs[i] = ++ readl(mvchip->membase + ++ GPIO_EDGE_MASK_MV78200_OFF(i)); ++ mvchip->level_mask_regs[i] = ++ readl(mvchip->membase + ++ GPIO_LEVEL_MASK_MV78200_OFF(i)); ++ } ++ break; ++ case MVEBU_GPIO_SOC_VARIANT_ARMADAXP: ++ for (i = 0; i < 4; i++) { ++ mvchip->edge_mask_regs[i] = ++ readl(mvchip->membase + ++ GPIO_EDGE_MASK_ARMADAXP_OFF(i)); ++ mvchip->level_mask_regs[i] = ++ readl(mvchip->membase + ++ GPIO_LEVEL_MASK_ARMADAXP_OFF(i)); ++ } ++ break; ++ default: ++ BUG(); ++ } ++ ++ return 0; ++} ++ ++static int mvebu_gpio_resume(struct platform_device *pdev) ++{ ++ struct mvebu_gpio_chip *mvchip = platform_get_drvdata(pdev); ++ int i; ++ ++ writel(mvchip->out_reg, mvebu_gpioreg_out(mvchip)); ++ writel(mvchip->io_conf_reg, mvebu_gpioreg_io_conf(mvchip)); ++ writel(mvchip->blink_en_reg, mvebu_gpioreg_blink(mvchip)); ++ writel(mvchip->in_pol_reg, mvebu_gpioreg_in_pol(mvchip)); ++ ++ switch (mvchip->soc_variant) { ++ case MVEBU_GPIO_SOC_VARIANT_ORION: ++ writel(mvchip->edge_mask_regs[0], ++ mvchip->membase + GPIO_EDGE_MASK_OFF); ++ writel(mvchip->level_mask_regs[0], ++ mvchip->membase + GPIO_LEVEL_MASK_OFF); ++ break; ++ case MVEBU_GPIO_SOC_VARIANT_MV78200: ++ for (i = 0; i < 2; i++) { ++ writel(mvchip->edge_mask_regs[i], ++ mvchip->membase + GPIO_EDGE_MASK_MV78200_OFF(i)); ++ writel(mvchip->level_mask_regs[i], ++ mvchip->membase + ++ GPIO_LEVEL_MASK_MV78200_OFF(i)); ++ } ++ break; ++ case MVEBU_GPIO_SOC_VARIANT_ARMADAXP: ++ for (i = 0; i < 4; i++) { ++ writel(mvchip->edge_mask_regs[i], ++ mvchip->membase + ++ GPIO_EDGE_MASK_ARMADAXP_OFF(i)); ++ writel(mvchip->level_mask_regs[i], ++ mvchip->membase + ++ GPIO_LEVEL_MASK_ARMADAXP_OFF(i)); ++ } ++ break; ++ default: ++ BUG(); ++ } ++ ++ return 0; ++} ++ + static int mvebu_gpio_probe(struct platform_device *pdev) + { + struct mvebu_gpio_chip *mvchip; +@@ -585,6 +680,8 @@ static int mvebu_gpio_probe(struct platf + if (!mvchip) + return -ENOMEM; + ++ platform_set_drvdata(pdev, mvchip); ++ + if (of_property_read_u32(pdev->dev.of_node, "ngpios", &ngpios)) { + dev_err(&pdev->dev, "Missing ngpios OF property\n"); + return -ENODEV; +@@ -743,5 +840,7 @@ static struct platform_driver mvebu_gpio + .of_match_table = mvebu_gpio_of_match, + }, + .probe = mvebu_gpio_probe, ++ .suspend = mvebu_gpio_suspend, ++ .resume = mvebu_gpio_resume, + }; + module_platform_driver(mvebu_gpio_driver); -- cgit v1.2.3