blob: 121e8a0da23fbd8cf2f10e7b075be0feb63a6ed1 [file] [log] [blame]
Duncan Laurieddc3e422013-10-02 16:10:54 -07001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright (C) 2008-2009 coresystems GmbH
5 * Copyright 2013 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.
Duncan Laurieddc3e422013-10-02 16:10:54 -070015 */
16
17#include <arch/io.h>
18#include <console/console.h>
19#include <cpu/x86/smm.h>
Julius Werner4ee4bd52014-10-20 13:46:39 -070020#include <soc/pm.h>
21#include <soc/smm.h>
Duncan Laurieddc3e422013-10-02 16:10:54 -070022#include <elog.h>
Duncan Laurieddc3e422013-10-02 16:10:54 -070023#include <ec/google/chromeec/ec.h>
Julius Werner4ee4bd52014-10-20 13:46:39 -070024#include <soc/gpio.h>
25#include <soc/iomap.h>
26#include <soc/nvs.h>
27#include <soc/pm.h>
28#include <soc/smm.h>
Duncan Laurieddc3e422013-10-02 16:10:54 -070029#include "ec.h"
Duncan Laurie1247b872014-09-29 08:35:29 -070030#include "gpio.h"
Duncan Laurieddc3e422013-10-02 16:10:54 -070031
Duncan Laurieddc3e422013-10-02 16:10:54 -070032static u8 mainboard_smi_ec(void)
33{
34 u8 cmd = google_chromeec_get_event();
35 u32 pm1_cnt;
36
37#if CONFIG_ELOG_GSMI
38 /* Log this event */
39 if (cmd)
40 elog_add_event_byte(ELOG_TYPE_EC_EVENT, cmd);
41#endif
42
43 switch (cmd) {
44 case EC_HOST_EVENT_LID_CLOSED:
45 printk(BIOS_DEBUG, "LID CLOSED, SHUTDOWN\n");
46
47 /* Go to S5 */
Duncan Laurie2663a552014-05-14 15:59:37 -070048 pm1_cnt = inl(ACPI_BASE_ADDRESS + PM1_CNT);
Duncan Laurieddc3e422013-10-02 16:10:54 -070049 pm1_cnt |= (0xf << 10);
Duncan Laurie2663a552014-05-14 15:59:37 -070050 outl(pm1_cnt, ACPI_BASE_ADDRESS + PM1_CNT);
Duncan Laurieddc3e422013-10-02 16:10:54 -070051 break;
52 }
53
54 return cmd;
55}
56
57/* gpi_sts is GPIO 47:32 */
58void mainboard_smi_gpi(u32 gpi_sts)
59{
60 if (gpi_sts & (1 << (EC_SMI_GPI - 32))) {
61 /* Process all pending events */
62 while (mainboard_smi_ec() != 0);
63 }
64}
65
Duncan Laurieddc3e422013-10-02 16:10:54 -070066void mainboard_smi_sleep(u8 slp_typ)
67{
68 /* Disable USB charging if required */
69 switch (slp_typ) {
70 case 3:
Duncan Laurie2663a552014-05-14 15:59:37 -070071 if (smm_get_gnvs()->s3u0 == 0) {
Duncan Laurieddc3e422013-10-02 16:10:54 -070072 google_chromeec_set_usb_charge_mode(
73 0, USB_CHARGE_MODE_DISABLED);
Duncan Laurieddc3e422013-10-02 16:10:54 -070074 google_chromeec_set_usb_charge_mode(
75 1, USB_CHARGE_MODE_DISABLED);
Duncan Laurie2663a552014-05-14 15:59:37 -070076 }
Duncan Laurieddc3e422013-10-02 16:10:54 -070077
Duncan Laurie5106b9d2014-06-10 10:05:03 -070078 /* Put SSD in reset to prevent leak. */
Duncan Laurie1247b872014-09-29 08:35:29 -070079 set_gpio(SAMUS_GPIO_SSD_RESET_L, 0);
Duncan Laurieddc3e422013-10-02 16:10:54 -070080 /* Prevent leak from standby rail to WLAN rail in S3. */
Duncan Laurie1247b872014-09-29 08:35:29 -070081 set_gpio(SAMUS_GPIO_WLAN_DISABLE_L, 0);
Duncan Laurieddc3e422013-10-02 16:10:54 -070082 /* Disable LTE */
Duncan Laurie1247b872014-09-29 08:35:29 -070083 set_gpio(SAMUS_GPIO_LTE_DISABLE_L, 0);
Duncan Laurieddc3e422013-10-02 16:10:54 -070084
85 /* Enable wake events */
86 google_chromeec_set_wake_mask(MAINBOARD_EC_S3_WAKE_EVENTS);
87 break;
88 case 5:
Duncan Laurie2663a552014-05-14 15:59:37 -070089 if (smm_get_gnvs()->s5u0 == 0) {
Duncan Laurieddc3e422013-10-02 16:10:54 -070090 google_chromeec_set_usb_charge_mode(
91 0, USB_CHARGE_MODE_DISABLED);
Duncan Laurieddc3e422013-10-02 16:10:54 -070092 google_chromeec_set_usb_charge_mode(
93 1, USB_CHARGE_MODE_DISABLED);
Duncan Laurie2663a552014-05-14 15:59:37 -070094 }
Duncan Laurieddc3e422013-10-02 16:10:54 -070095
Duncan Laurie5106b9d2014-06-10 10:05:03 -070096 /* Put SSD in reset to prevent leak. */
Duncan Laurie1247b872014-09-29 08:35:29 -070097 set_gpio(SAMUS_GPIO_SSD_RESET_L, 0);
Duncan Laurieddc3e422013-10-02 16:10:54 -070098 /* Prevent leak from standby rail to WLAN rail in S5. */
Duncan Laurie1247b872014-09-29 08:35:29 -070099 set_gpio(SAMUS_GPIO_WLAN_DISABLE_L, 0);
Duncan Laurieddc3e422013-10-02 16:10:54 -0700100 /* Disable LTE */
Duncan Laurie1247b872014-09-29 08:35:29 -0700101 set_gpio(SAMUS_GPIO_LTE_DISABLE_L, 0);
Duncan Laurieddc3e422013-10-02 16:10:54 -0700102
103 /* Enable wake events */
104 google_chromeec_set_wake_mask(MAINBOARD_EC_S5_WAKE_EVENTS);
105 break;
106 }
107
Duncan Laurieddc3e422013-10-02 16:10:54 -0700108 /* Disable SCI and SMI events */
109 google_chromeec_set_smi_mask(0);
110 google_chromeec_set_sci_mask(0);
111
112 /* Clear pending events that may trigger immediate wake */
113 while (google_chromeec_get_event() != 0);
114}
115
Duncan Laurieddc3e422013-10-02 16:10:54 -0700116int mainboard_smi_apmc(u8 apmc)
117{
118 switch (apmc) {
Duncan Laurieddc3e422013-10-02 16:10:54 -0700119 case APM_CNT_ACPI_ENABLE:
120 google_chromeec_set_smi_mask(0);
121 /* Clear all pending events */
122 while (google_chromeec_get_event() != 0);
123 google_chromeec_set_sci_mask(MAINBOARD_EC_SCI_EVENTS);
124 break;
125 case APM_CNT_ACPI_DISABLE:
126 google_chromeec_set_sci_mask(0);
127 /* Clear all pending events */
128 while (google_chromeec_get_event() != 0);
129 google_chromeec_set_smi_mask(MAINBOARD_EC_SMI_EVENTS);
130 break;
131 }
132 return 0;
133}