blob: 88400f76731b10b0094d258c360820b5e663027f [file] [log] [blame]
Lee Leahy89b5fbd2015-05-11 17:24:31 -07001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright (C) 2008-2009 coresystems GmbH
5 * Copyright (C) 2015 Intel Corp.
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; version 2 of the License.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
Lee Leahy89b5fbd2015-05-11 17:24:31 -070015 */
16
Aaron Durbin30b0c7a2016-07-13 13:01:13 -050017#include <arch/acpi.h>
Lee Leahy89b5fbd2015-05-11 17:24:31 -070018#include <arch/io.h>
Kyösti Mälkki13f66502019-03-03 08:01:05 +020019#include <device/mmio.h>
Lee Leahy89b5fbd2015-05-11 17:24:31 -070020#include <console/console.h>
21#include <cpu/x86/smm.h>
22#include "ec.h"
23#include <ec/google/chromeec/ec.h>
24#include <elog.h>
25#include <soc/nvs.h>
26#include <soc/pm.h>
27#include <soc/gpio.h>
28
Matt DeVilliere69a9c72017-08-20 14:48:57 -050029#include <variant/onboard.h>
Lee Leahy89b5fbd2015-05-11 17:24:31 -070030
31/* The wake gpio is SUS_GPIO[0]. */
32#define WAKE_GPIO_EN SUS_GPIO_EN0
Hannah Williams73600e32015-07-27 19:46:34 -070033#define GPIO_SUS7_WAKE_MASK (1 << 12)
34#define GPIO_SUS1_WAKE_MASK (1 << 13)
Lee Leahy89b5fbd2015-05-11 17:24:31 -070035
36int mainboard_io_trap_handler(int smif)
37{
38 switch (smif) {
39 case 0x99:
40 printk(BIOS_DEBUG, "Sample\n");
41 smm_get_gnvs()->smif = 0;
42 break;
43 default:
44 return 0;
45 }
46
47 /*
48 * On success, the IO Trap Handler returns 0
49 * On failure, the IO Trap Handler returns a value != 0
50 *
51 * For now, we force the return value to 0 and log all traps to
52 * see what's going on.
53 */
54 //gnvs->smif = 0;
55 return 1;
56}
57
58#if IS_ENABLED(CONFIG_EC_GOOGLE_CHROMEEC)
59static uint8_t mainboard_smi_ec(void)
60{
61 uint8_t cmd = google_chromeec_get_event();
62 uint16_t pmbase = get_pmbase();
63 uint32_t pm1_cnt;
64
65#if IS_ENABLED(CONFIG_ELOG_GSMI)
66 /* Log this event */
67 if (cmd)
68 elog_add_event_byte(ELOG_TYPE_EC_EVENT, cmd);
69#endif
70
71 switch (cmd) {
72 case EC_HOST_EVENT_LID_CLOSED:
73 printk(BIOS_DEBUG, "LID CLOSED, SHUTDOWN\n");
74
75 /* Go to S5 */
76 pm1_cnt = inl(pmbase + PM1_CNT);
77 pm1_cnt |= SLP_EN | (SLP_TYP_S5 << SLP_TYP_SHIFT);
78 outl(pm1_cnt, pmbase + PM1_CNT);
79 break;
80 }
81
82 return cmd;
83}
84#endif
85
86/*
87 * The entire 32-bit ALT_GPIO_SMI register is passed as a parameter. Note, that
88 * this includes the enable bits in the lower 16 bits.
89 */
90void mainboard_smi_gpi(uint32_t alt_gpio_smi)
91{
92#if IS_ENABLED(CONFIG_EC_GOOGLE_CHROMEEC)
93 if (alt_gpio_smi & (1 << EC_SMI_GPI)) {
94 /* Process all pending events */
95 while (mainboard_smi_ec() != 0)
96 ;
97 }
98#endif
99}
100
101void mainboard_smi_sleep(uint8_t slp_typ)
102{
Hannah Williams73600e32015-07-27 19:46:34 -0700103 void *addr;
104 uint32_t mask;
105
Lee Leahy89b5fbd2015-05-11 17:24:31 -0700106 /* Disable USB charging if required */
107 switch (slp_typ) {
Aaron Durbin30b0c7a2016-07-13 13:01:13 -0500108 case ACPI_S3:
Lee Leahy89b5fbd2015-05-11 17:24:31 -0700109#if IS_ENABLED(CONFIG_EC_GOOGLE_CHROMEEC)
110 if (smm_get_gnvs()->s3u0 == 0)
111 google_chromeec_set_usb_charge_mode(
112 0, USB_CHARGE_MODE_DISABLED);
113 if (smm_get_gnvs()->s3u1 == 0)
114 google_chromeec_set_usb_charge_mode(
115 1, USB_CHARGE_MODE_DISABLED);
116
117 /* Enable wake events */
118 google_chromeec_set_wake_mask(MAINBOARD_EC_S3_WAKE_EVENTS);
119#endif
120 /* Enable wake pin in GPE block. */
121 enable_gpe(WAKE_GPIO_EN);
122 break;
Aaron Durbin30b0c7a2016-07-13 13:01:13 -0500123 case ACPI_S5:
Lee Leahy89b5fbd2015-05-11 17:24:31 -0700124#if IS_ENABLED(CONFIG_EC_GOOGLE_CHROMEEC)
125 if (smm_get_gnvs()->s5u0 == 0)
126 google_chromeec_set_usb_charge_mode(
127 0, USB_CHARGE_MODE_DISABLED);
128 if (smm_get_gnvs()->s5u1 == 0)
129 google_chromeec_set_usb_charge_mode(
130 1, USB_CHARGE_MODE_DISABLED);
131
132 /* Enable wake events */
133 google_chromeec_set_wake_mask(MAINBOARD_EC_S5_WAKE_EVENTS);
134#endif
Hannah Williams73600e32015-07-27 19:46:34 -0700135
136 /* Disabling wake from SUS_GPIO1 (TOUCH INT) and
137 * SUS_GPIO7 (TRACKPAD INT) in North bank as they are not
138 * valid S5 wake sources
139 */
140 addr = (void *)(IO_BASE_ADDRESS + COMMUNITY_OFFSET_GPNORTH +
141 GPIO_WAKE_MASK_REG0);
142 mask = ~(GPIO_SUS1_WAKE_MASK | GPIO_SUS7_WAKE_MASK);
143 write32(addr, read32(addr) & mask);
144
Lee Leahy89b5fbd2015-05-11 17:24:31 -0700145 break;
146 }
147
148#if IS_ENABLED(CONFIG_EC_GOOGLE_CHROMEEC)
149 /* Disable SCI and SMI events */
150 google_chromeec_set_smi_mask(0);
151 google_chromeec_set_sci_mask(0);
152
153 /* Clear pending events that may trigger immediate wake */
154 while (google_chromeec_get_event() != 0)
155 ;
Matt DeVillier4f20a4a2017-08-20 17:56:48 -0500156
157 /* Set LPC lines to low power in S3/S5. */
158 if ((slp_typ == ACPI_S3) || (slp_typ == ACPI_S5)) {
159 lpc_set_low_power();
160 }
Lee Leahy89b5fbd2015-05-11 17:24:31 -0700161#endif
162}
163
164int mainboard_smi_apmc(uint8_t apmc)
165{
166 switch (apmc) {
167 case APM_CNT_ACPI_ENABLE:
168#if IS_ENABLED(CONFIG_EC_GOOGLE_CHROMEEC)
169 google_chromeec_set_smi_mask(0);
170 /* Clear all pending events */
171 while (google_chromeec_get_event() != 0)
172 ;
173 google_chromeec_set_sci_mask(MAINBOARD_EC_SCI_EVENTS);
174#endif
175 break;
176 case APM_CNT_ACPI_DISABLE:
177#if IS_ENABLED(CONFIG_EC_GOOGLE_CHROMEEC)
178 google_chromeec_set_sci_mask(0);
179 /* Clear all pending events */
180 while (google_chromeec_get_event() != 0)
181 ;
182 google_chromeec_set_smi_mask(MAINBOARD_EC_SMI_EVENTS);
183#endif
184 break;
185 }
186 return 0;
187}