kirkwood-pm.c 1.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. /*
  2. * Power Management driver for Marvell Kirkwood SoCs
  3. *
  4. * Copyright (C) 2013 Ezequiel Garcia <ezequiel@free-electrons.com>
  5. * Copyright (C) 2010 Simon Guinot <sguinot@lacie.com>
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License,
  9. * version 2 of the License.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. */
  16. #include <linux/kernel.h>
  17. #include <linux/suspend.h>
  18. #include <linux/io.h>
  19. #include "kirkwood.h"
  20. static void __iomem *ddr_operation_base;
  21. static void __iomem *memory_pm_ctrl;
  22. static void kirkwood_low_power(void)
  23. {
  24. u32 mem_pm_ctrl;
  25. mem_pm_ctrl = readl(memory_pm_ctrl);
  26. /* Set peripherals to low-power mode */
  27. writel_relaxed(~0, memory_pm_ctrl);
  28. /* Set DDR in self-refresh */
  29. writel_relaxed(0x7, ddr_operation_base);
  30. /*
  31. * Set CPU in wait-for-interrupt state.
  32. * This disables the CPU core clocks,
  33. * the array clocks, and also the L2 controller.
  34. */
  35. cpu_do_idle();
  36. writel_relaxed(mem_pm_ctrl, memory_pm_ctrl);
  37. }
  38. static int kirkwood_suspend_enter(suspend_state_t state)
  39. {
  40. switch (state) {
  41. case PM_SUSPEND_STANDBY:
  42. kirkwood_low_power();
  43. break;
  44. default:
  45. return -EINVAL;
  46. }
  47. return 0;
  48. }
  49. static int kirkwood_pm_valid_standby(suspend_state_t state)
  50. {
  51. return state == PM_SUSPEND_STANDBY;
  52. }
  53. static const struct platform_suspend_ops kirkwood_suspend_ops = {
  54. .enter = kirkwood_suspend_enter,
  55. .valid = kirkwood_pm_valid_standby,
  56. };
  57. int __init kirkwood_pm_init(void)
  58. {
  59. ddr_operation_base = ioremap(DDR_OPERATION_BASE, 4);
  60. memory_pm_ctrl = ioremap(MEMORY_PM_CTRL_PHYS, 4);
  61. suspend_set_ops(&kirkwood_suspend_ops);
  62. return 0;
  63. }