acpi-pmc-uclass.c 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright 2019 Google LLC
  4. */
  5. #define LOG_CATEGORY UCLASS_ACPI_PMC
  6. #include <common.h>
  7. #include <dm.h>
  8. #include <log.h>
  9. #include <spl.h>
  10. #include <acpi/acpi_s3.h>
  11. #ifdef CONFIG_X86
  12. #include <asm/intel_pinctrl.h>
  13. #endif
  14. #include <asm/io.h>
  15. #include <power/acpi_pmc.h>
  16. struct tco_regs {
  17. u32 tco_rld;
  18. u32 tco_sts;
  19. u32 tco1_cnt;
  20. u32 tco_tmr;
  21. };
  22. enum {
  23. TCO_STS_TIMEOUT = 1 << 3,
  24. TCO_STS_SECOND_TO_STS = 1 << 17,
  25. TCO1_CNT_HLT = 1 << 11,
  26. };
  27. #ifdef CONFIG_X86
  28. static int gpe0_shift(struct acpi_pmc_upriv *upriv, int regnum)
  29. {
  30. return upriv->gpe0_dwx_shift_base + regnum * 4;
  31. }
  32. int pmc_gpe_init(struct udevice *dev)
  33. {
  34. struct acpi_pmc_upriv *upriv = dev_get_uclass_priv(dev);
  35. struct udevice *itss;
  36. u32 *dw;
  37. u32 gpio_cfg_mask;
  38. u32 gpio_cfg;
  39. int ret, i;
  40. u32 mask;
  41. if (device_get_uclass_id(dev) != UCLASS_ACPI_PMC)
  42. return log_msg_ret("uclass", -EPROTONOSUPPORT);
  43. dw = upriv->gpe0_dw;
  44. mask = upriv->gpe0_dwx_mask;
  45. gpio_cfg_mask = 0;
  46. for (i = 0; i < upriv->gpe0_count; i++) {
  47. gpio_cfg_mask |= mask << gpe0_shift(upriv, i);
  48. if (dw[i] & ~mask)
  49. return log_msg_ret("Base GPE0 value", -EINVAL);
  50. }
  51. /*
  52. * Route the GPIOs to the GPE0 block. Determine that all values
  53. * are different and if they aren't, use the reset values.
  54. */
  55. if (dw[0] == dw[1] || dw[1] == dw[2]) {
  56. if (spl_phase() > PHASE_TPL)
  57. log_info("PMC: Using default GPE route");
  58. gpio_cfg = readl(upriv->gpe_cfg);
  59. for (i = 0; i < upriv->gpe0_count; i++)
  60. dw[i] = gpio_cfg >> gpe0_shift(upriv, i);
  61. } else {
  62. gpio_cfg = 0;
  63. for (i = 0; i < upriv->gpe0_count; i++)
  64. gpio_cfg |= dw[i] << gpe0_shift(upriv, i);
  65. clrsetbits_le32(upriv->gpe_cfg, gpio_cfg_mask, gpio_cfg);
  66. }
  67. /* Set the routes in the GPIO communities as well */
  68. ret = uclass_first_device_err(UCLASS_IRQ, &itss);
  69. if (ret)
  70. return log_msg_ret("Cannot find itss", ret);
  71. pinctrl_route_gpe(itss, dw[0], dw[1], dw[2]);
  72. return 0;
  73. }
  74. #endif /* CONFIG_X86 */
  75. static void pmc_fill_pm_reg_info(struct udevice *dev)
  76. {
  77. struct acpi_pmc_upriv *upriv = dev_get_uclass_priv(dev);
  78. int i;
  79. upriv->pm1_sts = inw(upriv->acpi_base + PM1_STS);
  80. upriv->pm1_en = inw(upriv->acpi_base + PM1_EN);
  81. upriv->pm1_cnt = inw(upriv->acpi_base + PM1_CNT);
  82. log_debug("pm1_sts: %04x pm1_en: %04x pm1_cnt: %08x\n",
  83. upriv->pm1_sts, upriv->pm1_en, upriv->pm1_cnt);
  84. for (i = 0; i < GPE0_REG_MAX; i++) {
  85. upriv->gpe0_sts[i] = inl(upriv->acpi_base + GPE0_STS + i * 4);
  86. upriv->gpe0_en[i] = inl(upriv->acpi_base + GPE0_EN + i * 4);
  87. log_debug("gpe0_sts[%d]: %08x gpe0_en[%d]: %08x\n", i,
  88. upriv->gpe0_sts[i], i, upriv->gpe0_en[i]);
  89. }
  90. }
  91. int pmc_disable_tco_base(ulong tco_base)
  92. {
  93. struct tco_regs *regs = (struct tco_regs *)tco_base;
  94. debug("tco_base %lx = %x\n", (ulong)&regs->tco1_cnt, TCO1_CNT_HLT);
  95. setio_32(&regs->tco1_cnt, TCO1_CNT_HLT);
  96. return 0;
  97. }
  98. int pmc_init(struct udevice *dev)
  99. {
  100. const struct acpi_pmc_ops *ops = acpi_pmc_get_ops(dev);
  101. int ret;
  102. pmc_fill_pm_reg_info(dev);
  103. if (!ops->init)
  104. return -ENOSYS;
  105. ret = ops->init(dev);
  106. if (ret)
  107. return log_msg_ret("Failed to init pmc", ret);
  108. #ifdef DEBUG
  109. pmc_dump_info(dev);
  110. #endif
  111. return 0;
  112. }
  113. int pmc_prev_sleep_state(struct udevice *dev)
  114. {
  115. struct acpi_pmc_upriv *upriv = dev_get_uclass_priv(dev);
  116. const struct acpi_pmc_ops *ops = acpi_pmc_get_ops(dev);
  117. int prev_sleep_state = ACPI_S0; /* Default to S0 */
  118. if (upriv->pm1_sts & WAK_STS) {
  119. switch (acpi_sleep_from_pm1(upriv->pm1_cnt)) {
  120. case ACPI_S3:
  121. if (IS_ENABLED(HAVE_ACPI_RESUME))
  122. prev_sleep_state = ACPI_S3;
  123. break;
  124. case ACPI_S5:
  125. prev_sleep_state = ACPI_S5;
  126. break;
  127. default:
  128. break;
  129. }
  130. /* Clear SLP_TYP */
  131. outl(upriv->pm1_cnt & ~SLP_TYP, upriv->acpi_base + PM1_CNT);
  132. }
  133. if (!ops->prev_sleep_state)
  134. return prev_sleep_state;
  135. return ops->prev_sleep_state(dev, prev_sleep_state);
  136. }
  137. int pmc_disable_tco(struct udevice *dev)
  138. {
  139. const struct acpi_pmc_ops *ops = acpi_pmc_get_ops(dev);
  140. pmc_fill_pm_reg_info(dev);
  141. if (!ops->disable_tco)
  142. return -ENOSYS;
  143. return ops->disable_tco(dev);
  144. }
  145. int pmc_global_reset_set_enable(struct udevice *dev, bool enable)
  146. {
  147. const struct acpi_pmc_ops *ops = acpi_pmc_get_ops(dev);
  148. if (!ops->global_reset_set_enable)
  149. return -ENOSYS;
  150. return ops->global_reset_set_enable(dev, enable);
  151. }
  152. void pmc_dump_info(struct udevice *dev)
  153. {
  154. struct acpi_pmc_upriv *upriv = dev_get_uclass_priv(dev);
  155. int i;
  156. printf("Device: %s\n", dev->name);
  157. printf("ACPI base %x, pmc_bar0 %p, pmc_bar2 %p, gpe_cfg %p\n",
  158. upriv->acpi_base, upriv->pmc_bar0, upriv->pmc_bar2,
  159. upriv->gpe_cfg);
  160. printf("pm1_sts: %04x pm1_en: %04x pm1_cnt: %08x\n",
  161. upriv->pm1_sts, upriv->pm1_en, upriv->pm1_cnt);
  162. for (i = 0; i < GPE0_REG_MAX; i++) {
  163. printf("gpe0_sts[%d]: %08x gpe0_en[%d]: %08x\n", i,
  164. upriv->gpe0_sts[i], i, upriv->gpe0_en[i]);
  165. }
  166. printf("prsts: %08x\n", upriv->prsts);
  167. printf("tco_sts: %04x %04x\n", upriv->tco1_sts, upriv->tco2_sts);
  168. printf("gen_pmcon1: %08x gen_pmcon2: %08x gen_pmcon3: %08x\n",
  169. upriv->gen_pmcon1, upriv->gen_pmcon2, upriv->gen_pmcon3);
  170. }
  171. int pmc_ofdata_to_uc_plat(struct udevice *dev)
  172. {
  173. struct acpi_pmc_upriv *upriv = dev_get_uclass_priv(dev);
  174. int ret;
  175. ret = dev_read_u32(dev, "gpe0-dwx-mask", &upriv->gpe0_dwx_mask);
  176. if (ret)
  177. return log_msg_ret("no gpe0-dwx-mask", ret);
  178. ret = dev_read_u32(dev, "gpe0-dwx-shift-base",
  179. &upriv->gpe0_dwx_shift_base);
  180. if (ret)
  181. return log_msg_ret("no gpe0-dwx-shift-base", ret);
  182. ret = dev_read_u32(dev, "gpe0-sts", &upriv->gpe0_sts_reg);
  183. if (ret)
  184. return log_msg_ret("no gpe0-sts", ret);
  185. upriv->gpe0_sts_reg += upriv->acpi_base;
  186. ret = dev_read_u32(dev, "gpe0-en", &upriv->gpe0_en_reg);
  187. if (ret)
  188. return log_msg_ret("no gpe0-en", ret);
  189. upriv->gpe0_en_reg += upriv->acpi_base;
  190. return 0;
  191. }
  192. UCLASS_DRIVER(acpi_pmc) = {
  193. .id = UCLASS_ACPI_PMC,
  194. .name = "power-mgr",
  195. .per_device_auto = sizeof(struct acpi_pmc_upriv),
  196. };