atcsmu.c 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. /*
  2. * SPDX-License-Identifier: BSD-3-Clause
  3. *
  4. * Copyright (c) 2023 Andes Technology Corporation
  5. *
  6. * Authors:
  7. * Yu Chien Peter Lin <peterlin@andestech.com>
  8. */
  9. #include <sbi_utils/sys/atcsmu.h>
  10. #include <sbi/riscv_io.h>
  11. #include <sbi/sbi_console.h>
  12. #include <sbi/sbi_error.h>
  13. #include <sbi/sbi_bitops.h>
  14. inline int smu_set_wakeup_events(struct smu_data *smu, u32 events, u32 hartid)
  15. {
  16. if (smu) {
  17. writel(events, (void *)(smu->addr + PCSm_WE_OFFSET(hartid)));
  18. return 0;
  19. } else
  20. return SBI_EINVAL;
  21. }
  22. inline bool smu_support_sleep_mode(struct smu_data *smu, u32 sleep_mode,
  23. u32 hartid)
  24. {
  25. u32 pcs_cfg;
  26. if (!smu) {
  27. sbi_printf("%s(): Failed to access smu_data\n", __func__);
  28. return false;
  29. }
  30. pcs_cfg = readl((void *)(smu->addr + PCSm_CFG_OFFSET(hartid)));
  31. switch (sleep_mode) {
  32. case LIGHTSLEEP_MODE:
  33. if (EXTRACT_FIELD(pcs_cfg, PCS_CFG_LIGHT_SLEEP) == 0) {
  34. sbi_printf(
  35. "SMU: hart%d (PCS%d) does not support light sleep mode\n",
  36. hartid, hartid + 3);
  37. return false;
  38. }
  39. break;
  40. case DEEPSLEEP_MODE:
  41. if (EXTRACT_FIELD(pcs_cfg, PCS_CFG_DEEP_SLEEP) == 0) {
  42. sbi_printf(
  43. "SMU: hart%d (PCS%d) does not support deep sleep mode\n",
  44. hartid, hartid + 3);
  45. return false;
  46. }
  47. break;
  48. }
  49. return true;
  50. }
  51. inline int smu_set_command(struct smu_data *smu, u32 pcs_ctl, u32 hartid)
  52. {
  53. if (smu) {
  54. writel(pcs_ctl, (void *)(smu->addr + PCSm_CTL_OFFSET(hartid)));
  55. return 0;
  56. } else
  57. return SBI_EINVAL;
  58. }
  59. inline int smu_set_reset_vector(struct smu_data *smu, ulong wakeup_addr,
  60. u32 hartid)
  61. {
  62. u32 vec_lo, vec_hi;
  63. u64 reset_vector;
  64. if (!smu)
  65. return SBI_EINVAL;
  66. writel(wakeup_addr, (void *)(smu->addr + HARTn_RESET_VEC_LO(hartid)));
  67. writel((u64)wakeup_addr >> 32,
  68. (void *)(smu->addr + HARTn_RESET_VEC_HI(hartid)));
  69. vec_lo = readl((void *)(smu->addr + HARTn_RESET_VEC_LO(hartid)));
  70. vec_hi = readl((void *)(smu->addr + HARTn_RESET_VEC_HI(hartid)));
  71. reset_vector = ((u64)vec_hi << 32) | vec_lo;
  72. if (reset_vector != (u64)wakeup_addr) {
  73. sbi_printf(
  74. "hard%d (PCS%d): Failed to program the reset vector.\n",
  75. hartid, hartid + 3);
  76. return SBI_EFAIL;
  77. } else
  78. return 0;
  79. }