pm.c 2.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. /*
  2. * arch/sh/kernel/cpu/shmobile/pm.c
  3. *
  4. * Power management support code for SuperH Mobile
  5. *
  6. * Copyright (C) 2009 Magnus Damm
  7. *
  8. * This file is subject to the terms and conditions of the GNU General Public
  9. * License. See the file "COPYING" in the main directory of this archive
  10. * for more details.
  11. */
  12. #include <linux/init.h>
  13. #include <linux/kernel.h>
  14. #include <linux/io.h>
  15. #include <linux/suspend.h>
  16. #include <asm/suspend.h>
  17. #include <asm/uaccess.h>
  18. /*
  19. * Sleep modes available on SuperH Mobile:
  20. *
  21. * Sleep mode is just plain "sleep" instruction
  22. * Sleep Self-Refresh mode is above plus RAM put in Self-Refresh
  23. * Standby Self-Refresh mode is above plus stopped clocks
  24. */
  25. #define SUSP_MODE_SLEEP (SUSP_SH_SLEEP)
  26. #define SUSP_MODE_SLEEP_SF (SUSP_SH_SLEEP | SUSP_SH_SF)
  27. #define SUSP_MODE_STANDBY_SF (SUSP_SH_STANDBY | SUSP_SH_SF)
  28. /*
  29. * The following modes are not there yet:
  30. *
  31. * R-standby mode is unsupported, but will be added in the future
  32. * U-standby mode is low priority since it needs bootloader hacks
  33. */
  34. #define ILRAM_BASE 0xe5200000
  35. extern const unsigned char sh_mobile_standby[];
  36. extern const unsigned int sh_mobile_standby_size;
  37. void sh_mobile_call_standby(unsigned long mode)
  38. {
  39. void *onchip_mem = (void *)ILRAM_BASE;
  40. void (*standby_onchip_mem)(unsigned long, unsigned long) = onchip_mem;
  41. /* Let assembly snippet in on-chip memory handle the rest */
  42. standby_onchip_mem(mode, ILRAM_BASE);
  43. }
  44. static int sh_pm_enter(suspend_state_t state)
  45. {
  46. local_irq_disable();
  47. set_bl_bit();
  48. sh_mobile_call_standby(SUSP_MODE_STANDBY_SF);
  49. local_irq_disable();
  50. clear_bl_bit();
  51. return 0;
  52. }
  53. static struct platform_suspend_ops sh_pm_ops = {
  54. .enter = sh_pm_enter,
  55. .valid = suspend_valid_only_mem,
  56. };
  57. static int __init sh_pm_init(void)
  58. {
  59. void *onchip_mem = (void *)ILRAM_BASE;
  60. /* Copy the assembly snippet to the otherwise ununsed ILRAM */
  61. memcpy(onchip_mem, sh_mobile_standby, sh_mobile_standby_size);
  62. wmb();
  63. ctrl_barrier();
  64. suspend_set_ops(&sh_pm_ops);
  65. sh_mobile_setup_cpuidle();
  66. return 0;
  67. }
  68. late_initcall(sh_pm_init);