blob: ff98b367d555fb9b2c9340ca4be8c39b7d5f4499 [file] [log] [blame]
Patrick Georgi406313d2015-07-20 22:01:32 +02001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright (C) 2008-2009 coresystems GmbH
5 * Copyright (C) 2015 Google Inc.
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.
Patrick Georgi406313d2015-07-20 22:01:32 +020015 */
16
Aaron Durbin30b0c7a2016-07-13 13:01:13 -050017#include <arch/acpi.h>
Patrick Georgi406313d2015-07-20 22:01:32 +020018#include <arch/io.h>
19#include <console/console.h>
20#include <cpu/x86/smm.h>
21#include <elog.h>
22#include <ec/google/chromeec/ec.h>
Aaron Durbince6c3562015-11-11 16:46:27 -060023#include <gpio.h>
Patrick Georgi406313d2015-07-20 22:01:32 +020024#include <soc/iomap.h>
25#include <soc/nvs.h>
26#include <soc/pm.h>
27#include <soc/smm.h>
28#include "ec.h"
Duncan Laurie56260852015-08-17 09:53:22 -070029#include "gpio.h"
Patrick Georgi406313d2015-07-20 22:01:32 +020030
31int mainboard_io_trap_handler(int smif)
32{
33 switch (smif) {
34 case 0x99:
35 printk(BIOS_DEBUG, "Sample\n");
36 smm_get_gnvs()->smif = 0;
37 break;
38 default:
39 return 0;
40 }
41
42 /* On success, the IO Trap Handler returns 0
43 * On failure, the IO Trap Handler returns a value != 0
44 *
45 * For now, we force the return value to 0 and log all traps to
46 * see what's going on.
47 */
48 return 1;
49}
50
51static u8 mainboard_smi_ec(void)
52{
53 u8 cmd = 0;
54#if IS_ENABLED(CONFIG_EC_GOOGLE_CHROMEEC)
55 u32 pm1_cnt;
56 cmd = google_chromeec_get_event();
57
58 /* Log this event */
59 if (IS_ENABLED(CONFIG_ELOG_GSMI) && cmd)
60 elog_add_event_byte(ELOG_TYPE_EC_EVENT, cmd);
61
62 switch (cmd) {
63 case EC_HOST_EVENT_LID_CLOSED:
64 printk(BIOS_DEBUG, "LID CLOSED, SHUTDOWN\n");
65
66 /* Go to S5 */
67 pm1_cnt = inl(ACPI_BASE_ADDRESS + PM1_CNT);
68 pm1_cnt |= (0xf << 10);
69 outl(pm1_cnt, ACPI_BASE_ADDRESS + PM1_CNT);
70 break;
71 }
72#endif
73 return cmd;
74}
75
Aaron Durbin50ed38f2015-08-08 01:25:21 -050076void mainboard_smi_gpi_handler(const struct gpi_status *sts)
Patrick Georgi406313d2015-07-20 22:01:32 +020077{
Aaron Durbin50ed38f2015-08-08 01:25:21 -050078 if (gpi_status_get(sts, EC_SMI_GPI)) {
Patrick Georgi406313d2015-07-20 22:01:32 +020079 /* Process all pending events */
80 while (mainboard_smi_ec() != 0)
81 ;
82 }
83}
84
Aaron Durbince6c3562015-11-11 16:46:27 -060085static void google_ec_smi_sleep(u8 slp_typ)
Patrick Georgi406313d2015-07-20 22:01:32 +020086{
Patrick Georgi406313d2015-07-20 22:01:32 +020087 switch (slp_typ) {
Aaron Durbin30b0c7a2016-07-13 13:01:13 -050088 case ACPI_S3:
Patrick Georgi406313d2015-07-20 22:01:32 +020089 /* Enable wake events */
90 google_chromeec_set_wake_mask(MAINBOARD_EC_S3_WAKE_EVENTS);
91 break;
Aaron Durbin30b0c7a2016-07-13 13:01:13 -050092 case ACPI_S5:
Patrick Georgi406313d2015-07-20 22:01:32 +020093 /* Enable wake events */
94 google_chromeec_set_wake_mask(MAINBOARD_EC_S5_WAKE_EVENTS);
95 break;
96 }
97
98 /* Disable SCI and SMI events */
99 google_chromeec_set_smi_mask(0);
100 google_chromeec_set_sci_mask(0);
101
102 /* Clear pending events that may trigger immediate wake */
103 while (google_chromeec_get_event() != 0)
104 ;
Aaron Durbince6c3562015-11-11 16:46:27 -0600105}
106
107static void mainboard_gpio_smi_sleep(u8 slp_typ)
108{
109 int i;
110
111 /* Power down the rails on any sleep type. */
112 gpio_t active_high_signals[] = {
113 EN_PP3300_KEPLER,
114 EN_PP3300_DX_TOUCH,
115 EN_PP3300_DX_EMMC,
116 EN_PP1800_DX_EMMC,
117 EN_PP3300_DX_CAM,
118 };
119
120 for (i = 0; i < ARRAY_SIZE(active_high_signals); i++)
121 gpio_set(active_high_signals[i], 0);
122}
123
124void mainboard_smi_sleep(u8 slp_typ)
125{
126 if (IS_ENABLED(CONFIG_EC_GOOGLE_CHROMEEC))
127 google_ec_smi_sleep(slp_typ);
128
129 mainboard_gpio_smi_sleep(slp_typ);
Patrick Georgi406313d2015-07-20 22:01:32 +0200130}
131
132int mainboard_smi_apmc(u8 apmc)
133{
134#if IS_ENABLED(CONFIG_EC_GOOGLE_CHROMEEC)
135 switch (apmc) {
136 case APM_CNT_ACPI_ENABLE:
137 google_chromeec_set_smi_mask(0);
138 /* Clear all pending events */
139 while (google_chromeec_get_event() != 0)
140 ;
141 google_chromeec_set_sci_mask(MAINBOARD_EC_SCI_EVENTS);
142 break;
143 case APM_CNT_ACPI_DISABLE:
144 google_chromeec_set_sci_mask(0);
145 /* Clear all pending events */
146 while (google_chromeec_get_event() != 0)
147 ;
148 google_chromeec_set_smi_mask(MAINBOARD_EC_SMI_EVENTS);
149 break;
150 }
151#endif
152 return 0;
153}