ec_lenovo.go 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  1. package main
  2. import "fmt"
  3. func LenovoEC(ctx Context) {
  4. ap := Create(ctx, "acpi/platform.asl")
  5. defer ap.Close()
  6. wakeGPE := 13
  7. sbGPE := GuessECGPE(ctx)
  8. var GPE int
  9. var GPEUnsure bool
  10. if sbGPE < 0 {
  11. sbGPE = SouthBridge.EncodeGPE(1)
  12. GPE = 1
  13. GPEUnsure = true
  14. SouthBridge.NeedRouteGPIOManually()
  15. } else {
  16. GPE = SouthBridge.DecodeGPE(sbGPE)
  17. GPEUnsure = false
  18. }
  19. SouthBridge.EnableGPE(wakeGPE)
  20. SouthBridge.EnableGPE(GPE)
  21. GPEDefine := DSDTDefine{
  22. Key: "THINKPAD_EC_GPE",
  23. }
  24. GPEDefine.Value = fmt.Sprintf("%d", sbGPE)
  25. if GPEUnsure {
  26. GPEDefine.Comment = "FIXME: Check this"
  27. }
  28. DSDTDefines = append(DSDTDefines,
  29. DSDTDefine{
  30. Key: "EC_LENOVO_H8_ME_WORKAROUND",
  31. Value: "1",
  32. }, GPEDefine)
  33. Add_gpl(ap)
  34. ap.WriteString(
  35. `Method(_WAK, 1)
  36. {
  37. /* ME may not be up yet. */
  38. Store(0, \_TZ.MEB1)
  39. Store(0, \_TZ.MEB2)
  40. Return(Package() {0, 0})
  41. }
  42. Method(_PTS,1)
  43. {
  44. \_SB.PCI0.LPCB.EC.RADI(0)
  45. }
  46. `)
  47. si := Create(ctx, "acpi/superio.asl")
  48. defer si.Close()
  49. Add_gpl(si)
  50. si.WriteString("#include <drivers/pc80/pc/ps2_controller.asl>\n")
  51. /* FIXME:XX Move this to ec/lenovo. */
  52. smi := Create(ctx, "smihandler.c")
  53. defer smi.Close()
  54. AddSMMFile("smihandler.c", "")
  55. Add_gpl(smi)
  56. smi.WriteString(
  57. `#include <arch/io.h>
  58. #include <console/console.h>
  59. #include <cpu/x86/smm.h>
  60. #include <ec/acpi/ec.h>
  61. #include <ec/lenovo/h8/h8.h>
  62. #include <delay.h>
  63. #include <` + SouthBridge.GetGPIOHeader() + ">\n\n")
  64. if GPEUnsure {
  65. smi.WriteString("/* FIXME: check this */\n")
  66. }
  67. fmt.Fprintf(smi, "#define GPE_EC_SCI %d\n", GPE)
  68. smi.WriteString("/* FIXME: check this */\n")
  69. fmt.Fprintf(smi, "#define GPE_EC_WAKE %d\n", wakeGPE)
  70. smi.WriteString(`
  71. static void mainboard_smi_handle_ec_sci(void)
  72. {
  73. u8 status = inb(EC_SC);
  74. u8 event;
  75. if (!(status & EC_SCI_EVT))
  76. return;
  77. event = ec_query();
  78. printk(BIOS_DEBUG, "EC event %#02x\n", event);
  79. }
  80. void mainboard_smi_gpi(u32 gpi_sts)
  81. {
  82. if (gpi_sts & (1 << GPE_EC_SCI))
  83. mainboard_smi_handle_ec_sci();
  84. }
  85. int mainboard_smi_apmc(u8 data)
  86. {
  87. switch (data) {
  88. case APM_CNT_ACPI_ENABLE:
  89. /* use 0x1600/0x1604 to prevent races with userspace */
  90. ec_set_ports(0x1604, 0x1600);
  91. /* route EC_SCI to SCI */
  92. gpi_route_interrupt(GPE_EC_SCI, GPI_IS_SCI);
  93. /* discard all events, and enable attention */
  94. ec_write(0x80, 0x01);
  95. break;
  96. case APM_CNT_ACPI_DISABLE:
  97. /* we have to use port 0x62/0x66, as 0x1600/0x1604 doesn't
  98. provide a EC query function */
  99. ec_set_ports(0x66, 0x62);
  100. /* route EC_SCI to SMI */
  101. gpi_route_interrupt(GPE_EC_SCI, GPI_IS_SMI);
  102. /* discard all events, and enable attention */
  103. ec_write(0x80, 0x01);
  104. break;
  105. default:
  106. break;
  107. }
  108. return 0;
  109. }
  110. void mainboard_smi_sleep(u8 slp_typ)
  111. {
  112. if (slp_typ == 3) {
  113. u8 ec_wake = ec_read(0x32);
  114. /* If EC wake events are enabled, enable wake on EC WAKE GPE. */
  115. if (ec_wake & 0x14) {
  116. /* Redirect EC WAKE GPE to SCI. */
  117. gpi_route_interrupt(GPE_EC_WAKE, GPI_IS_SCI);
  118. }
  119. }
  120. }
  121. `)
  122. ec := Create(ctx, "acpi/ec.asl")
  123. defer ec.Close()
  124. Add_gpl(ec)
  125. ec.WriteString("#include <ec/lenovo/h8/acpi/ec.asl>\n")
  126. KconfigBool["EC_LENOVO_PMH7"] = true
  127. KconfigBool["EC_LENOVO_H8"] = true
  128. pmh := DevTreeNode{
  129. Chip: "ec/lenovo/pmh7",
  130. Registers: map[string]string{
  131. "backlight_enable": "true",
  132. "dock_event_enable": "true",
  133. },
  134. Children: []DevTreeNode{
  135. DevTreeNode{
  136. Chip: "pnp",
  137. Comment: "dummy",
  138. Dev: 0xff,
  139. Func: 1,
  140. },
  141. },
  142. }
  143. PutChip("lpc", pmh)
  144. ecs := ctx.InfoSource.GetEC()
  145. h8 := DevTreeNode{
  146. Chip: "ec/lenovo/h8",
  147. Children: []DevTreeNode{
  148. DevTreeNode{
  149. Chip: "pnp",
  150. Comment: "dummy",
  151. Dev: 0xff,
  152. Func: 2,
  153. IOs: map[uint16]uint16{
  154. 0x60: 0x62,
  155. 0x62: 0x66,
  156. 0x64: 0x1600,
  157. 0x66: 0x1604,
  158. },
  159. },
  160. },
  161. Comment: "FIXME: has_keyboard_backlight, has_power_management_beeps, has_uwb",
  162. Registers: map[string]string{
  163. "config0": FormatHex8(ecs[0]),
  164. "config1": FormatHex8(ecs[1]),
  165. "config2": FormatHex8(ecs[2]),
  166. "config3": FormatHex8(ecs[3]),
  167. "beepmask0": FormatHex8(ecs[4]),
  168. "beepmask1": FormatHex8(ecs[5]),
  169. },
  170. }
  171. for i := 0; i < 0x10; i++ {
  172. if ecs[0x10+i] != 0 {
  173. h8.Registers[fmt.Sprintf("event%x_enable", i)] = FormatHex8(ecs[0x10+i])
  174. }
  175. }
  176. PutChip("lpc", h8)
  177. eeprom := DevTreeNode{
  178. Chip: "drivers/i2c/at24rf08c",
  179. Comment: "eeprom, 8 virtual devices, same chip",
  180. Children: []DevTreeNode{
  181. DevTreeNode{
  182. Chip: "i2c",
  183. Dev: 0x54,
  184. },
  185. DevTreeNode{
  186. Chip: "i2c",
  187. Dev: 0x55,
  188. },
  189. DevTreeNode{
  190. Chip: "i2c",
  191. Dev: 0x56,
  192. },
  193. DevTreeNode{
  194. Chip: "i2c",
  195. Dev: 0x57,
  196. },
  197. DevTreeNode{
  198. Chip: "i2c",
  199. Dev: 0x5c,
  200. },
  201. DevTreeNode{
  202. Chip: "i2c",
  203. Dev: 0x5d,
  204. },
  205. DevTreeNode{
  206. Chip: "i2c",
  207. Dev: 0x5e,
  208. },
  209. DevTreeNode{
  210. Chip: "i2c",
  211. Dev: 0x5f,
  212. },
  213. },
  214. }
  215. PutChip("smbus", eeprom)
  216. }