soc_powergate.c 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. /*
  2. * Copyright (c) 2018 Actions Semiconductor Co., Ltd
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. /**
  7. * @file system reboot interface for Actions SoC
  8. */
  9. #include <device.h>
  10. #include <init.h>
  11. #include <soc.h>
  12. #include <pm/pm.h>
  13. #include <linker/linker-defs.h>
  14. #define PWRGATE_MAINCPU_PG_BIT 31
  15. #define PWRGATE_BT_PG_BIT 28
  16. #define PWRGATE_DSP_AU_PG_BIT 26
  17. #define PWRGATE_GPU_PG_BIT 25
  18. #define PWRGATE_DISPLAY_PG_BIT 21
  19. static uint8_t g_pd_cnt[POWERGATE_MAX_DEV];
  20. static uint32_t soc_powerate_bit(uint8_t pg_dev)
  21. {
  22. switch(pg_dev){
  23. case POWERGATE_DISPLAY_PG_DEV:
  24. return PWRGATE_DISPLAY_PG_BIT;
  25. case POWERGATE_GPU_PG_DEV:
  26. return PWRGATE_GPU_PG_BIT;
  27. case POWERGATE_DSP_AU_PG_DEV:
  28. return PWRGATE_DSP_AU_PG_BIT;
  29. case POWERGATE_BT_PG_DEV:
  30. return PWRGATE_BT_PG_BIT;
  31. case PWRGATE_MAINCPU_PG_DEV:
  32. return PWRGATE_MAINCPU_PG_BIT;
  33. }
  34. return 0;
  35. }
  36. bool soc_powergate_is_poweron(uint8_t pg_dev)
  37. {
  38. uint32_t bit_num;
  39. if(pg_dev >= POWERGATE_MAX_DEV)
  40. return false;
  41. bit_num = soc_powerate_bit(pg_dev);
  42. return !!(sys_test_bit(PWRGATE_DIG, bit_num));
  43. }
  44. int soc_powergate_set(uint8_t pg_dev, bool power_on)
  45. {
  46. uint32_t key, bit_num, val, timeout;
  47. bool is_update;
  48. if(pg_dev >= POWERGATE_MAX_DEV){
  49. printk("error-pg:no dev=%d\n", pg_dev);
  50. return -1;
  51. }
  52. key = irq_lock();
  53. if(power_on){
  54. if(g_pd_cnt[pg_dev] > 128){
  55. printk("error-pg: dev=%d is poweron over max num\n", pg_dev);
  56. }else{
  57. g_pd_cnt[pg_dev]++;
  58. }
  59. }else{
  60. if(g_pd_cnt[pg_dev]){
  61. g_pd_cnt[pg_dev]--;
  62. }else{
  63. printk("error-pg: dev=%d is poweroff\n", pg_dev);
  64. }
  65. }
  66. bit_num = soc_powerate_bit(pg_dev);
  67. val = sys_read32(PWRGATE_DIG);
  68. sl_dbg("pg:dev=%d num=%d, onoff=%d,reg=0x%x\n", pg_dev, g_pd_cnt[pg_dev], power_on, val);
  69. is_update = false;
  70. if(g_pd_cnt[pg_dev]){
  71. if(!(val & (1<<bit_num))){// if power off, power on
  72. val |= (1<<bit_num);
  73. is_update = true;
  74. sl_dbg("pg:dev=%d is poweron\n", pg_dev);
  75. }
  76. }else{
  77. if(val & (1<<bit_num)){// if power on , power off
  78. val &= ~(1<<bit_num);
  79. is_update = true;
  80. sl_dbg("pg: dev=%d is poweroff\n", pg_dev);
  81. }
  82. }
  83. if(is_update) {
  84. sys_write32(val, PWRGATE_DIG);
  85. timeout = 1000; /* 1ms */
  86. while (timeout > 0) {
  87. if(sys_test_bit(PWRGATE_DIG_ACK, bit_num))
  88. break;
  89. soc_udelay(10);
  90. timeout -= 10;
  91. }
  92. }
  93. irq_unlock(key);
  94. return g_pd_cnt[pg_dev];
  95. }
  96. void soc_powergate_init(void)
  97. {
  98. uint32_t i, bit_num, val;
  99. val = sys_read32(PWRGATE_DIG);
  100. printk("PWRGATE_DIG=0x%x\n", val);
  101. for(i = 0; i < POWERGATE_MAX_DEV; i++){
  102. bit_num = soc_powerate_bit(i);
  103. if(val & (1 << bit_num)){
  104. g_pd_cnt[i] = 1;
  105. printk("pg: dev=%d is poweron, num=%d\n", i, g_pd_cnt[i]);
  106. }else{
  107. g_pd_cnt[i] = 0;
  108. printk("pg: dev=%d is poweroff, num=%d\n", i, g_pd_cnt[i]);
  109. }
  110. }
  111. }
  112. void soc_powergate_dump(void)
  113. {
  114. uint32_t i, bit_num, val;
  115. val = sys_read32(PWRGATE_DIG);
  116. for(i = 0; i < POWERGATE_MAX_DEV; i++){
  117. bit_num = soc_powerate_bit(i);
  118. if(val & (1 << bit_num)){
  119. printk("pg: dev=%d is poweron, num=%d\n", i, g_pd_cnt[i]);
  120. }else{
  121. printk("pg: dev=%d is poweroff, num=%d\n", i, g_pd_cnt[i]);
  122. }
  123. }
  124. }