198-gpio_mvebu_suspend.patch 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. This commit adds the implementation of ->suspend() and ->resume()
  2. platform_driver hooks in order to save and restore the state of the
  3. GPIO configuration. In order to achieve that, additional fields are
  4. added to the mvebu_gpio_chip structure.
  5. Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
  6. Acked-by: Alexandre Courbot <acourbot@nvidia.com>
  7. Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
  8. --- a/drivers/gpio/gpio-mvebu.c
  9. +++ b/drivers/gpio/gpio-mvebu.c
  10. @@ -83,6 +83,14 @@ struct mvebu_gpio_chip {
  11. int irqbase;
  12. struct irq_domain *domain;
  13. int soc_variant;
  14. +
  15. + /* Used to preserve GPIO registers accross suspend/resume */
  16. + u32 out_reg;
  17. + u32 io_conf_reg;
  18. + u32 blink_en_reg;
  19. + u32 in_pol_reg;
  20. + u32 edge_mask_regs[4];
  21. + u32 level_mask_regs[4];
  22. };
  23. /*
  24. @@ -562,6 +570,93 @@ static const struct of_device_id mvebu_g
  25. };
  26. MODULE_DEVICE_TABLE(of, mvebu_gpio_of_match);
  27. +static int mvebu_gpio_suspend(struct platform_device *pdev, pm_message_t state)
  28. +{
  29. + struct mvebu_gpio_chip *mvchip = platform_get_drvdata(pdev);
  30. + int i;
  31. +
  32. + mvchip->out_reg = readl(mvebu_gpioreg_out(mvchip));
  33. + mvchip->io_conf_reg = readl(mvebu_gpioreg_io_conf(mvchip));
  34. + mvchip->blink_en_reg = readl(mvebu_gpioreg_blink(mvchip));
  35. + mvchip->in_pol_reg = readl(mvebu_gpioreg_in_pol(mvchip));
  36. +
  37. + switch (mvchip->soc_variant) {
  38. + case MVEBU_GPIO_SOC_VARIANT_ORION:
  39. + mvchip->edge_mask_regs[0] =
  40. + readl(mvchip->membase + GPIO_EDGE_MASK_OFF);
  41. + mvchip->level_mask_regs[0] =
  42. + readl(mvchip->membase + GPIO_LEVEL_MASK_OFF);
  43. + break;
  44. + case MVEBU_GPIO_SOC_VARIANT_MV78200:
  45. + for (i = 0; i < 2; i++) {
  46. + mvchip->edge_mask_regs[i] =
  47. + readl(mvchip->membase +
  48. + GPIO_EDGE_MASK_MV78200_OFF(i));
  49. + mvchip->level_mask_regs[i] =
  50. + readl(mvchip->membase +
  51. + GPIO_LEVEL_MASK_MV78200_OFF(i));
  52. + }
  53. + break;
  54. + case MVEBU_GPIO_SOC_VARIANT_ARMADAXP:
  55. + for (i = 0; i < 4; i++) {
  56. + mvchip->edge_mask_regs[i] =
  57. + readl(mvchip->membase +
  58. + GPIO_EDGE_MASK_ARMADAXP_OFF(i));
  59. + mvchip->level_mask_regs[i] =
  60. + readl(mvchip->membase +
  61. + GPIO_LEVEL_MASK_ARMADAXP_OFF(i));
  62. + }
  63. + break;
  64. + default:
  65. + BUG();
  66. + }
  67. +
  68. + return 0;
  69. +}
  70. +
  71. +static int mvebu_gpio_resume(struct platform_device *pdev)
  72. +{
  73. + struct mvebu_gpio_chip *mvchip = platform_get_drvdata(pdev);
  74. + int i;
  75. +
  76. + writel(mvchip->out_reg, mvebu_gpioreg_out(mvchip));
  77. + writel(mvchip->io_conf_reg, mvebu_gpioreg_io_conf(mvchip));
  78. + writel(mvchip->blink_en_reg, mvebu_gpioreg_blink(mvchip));
  79. + writel(mvchip->in_pol_reg, mvebu_gpioreg_in_pol(mvchip));
  80. +
  81. + switch (mvchip->soc_variant) {
  82. + case MVEBU_GPIO_SOC_VARIANT_ORION:
  83. + writel(mvchip->edge_mask_regs[0],
  84. + mvchip->membase + GPIO_EDGE_MASK_OFF);
  85. + writel(mvchip->level_mask_regs[0],
  86. + mvchip->membase + GPIO_LEVEL_MASK_OFF);
  87. + break;
  88. + case MVEBU_GPIO_SOC_VARIANT_MV78200:
  89. + for (i = 0; i < 2; i++) {
  90. + writel(mvchip->edge_mask_regs[i],
  91. + mvchip->membase + GPIO_EDGE_MASK_MV78200_OFF(i));
  92. + writel(mvchip->level_mask_regs[i],
  93. + mvchip->membase +
  94. + GPIO_LEVEL_MASK_MV78200_OFF(i));
  95. + }
  96. + break;
  97. + case MVEBU_GPIO_SOC_VARIANT_ARMADAXP:
  98. + for (i = 0; i < 4; i++) {
  99. + writel(mvchip->edge_mask_regs[i],
  100. + mvchip->membase +
  101. + GPIO_EDGE_MASK_ARMADAXP_OFF(i));
  102. + writel(mvchip->level_mask_regs[i],
  103. + mvchip->membase +
  104. + GPIO_LEVEL_MASK_ARMADAXP_OFF(i));
  105. + }
  106. + break;
  107. + default:
  108. + BUG();
  109. + }
  110. +
  111. + return 0;
  112. +}
  113. +
  114. static int mvebu_gpio_probe(struct platform_device *pdev)
  115. {
  116. struct mvebu_gpio_chip *mvchip;
  117. @@ -585,6 +680,8 @@ static int mvebu_gpio_probe(struct platf
  118. if (!mvchip)
  119. return -ENOMEM;
  120. + platform_set_drvdata(pdev, mvchip);
  121. +
  122. if (of_property_read_u32(pdev->dev.of_node, "ngpios", &ngpios)) {
  123. dev_err(&pdev->dev, "Missing ngpios OF property\n");
  124. return -ENODEV;
  125. @@ -743,5 +840,7 @@ static struct platform_driver mvebu_gpio
  126. .of_match_table = mvebu_gpio_of_match,
  127. },
  128. .probe = mvebu_gpio_probe,
  129. + .suspend = mvebu_gpio_suspend,
  130. + .resume = mvebu_gpio_resume,
  131. };
  132. module_platform_driver(mvebu_gpio_driver);