blob: 8318050ce09f06570432711b1748b9ca69a6282f [file] [log] [blame]
Lee Leahy77ff0b12015-05-05 15:07:29 -07001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright (C) 2013 Google Inc.
Lee Leahy32471722015-04-20 15:20:28 -07005 * Copyright (C) 2015 Intel Corp.
Lee Leahy77ff0b12015-05-05 15:07:29 -07006 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation; version 2 of
10 * the License.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
Lee Leahy77ff0b12015-05-05 15:07:29 -070016 */
17
Lee Leahy77ff0b12015-05-05 15:07:29 -070018#include <arch/io.h>
Lee Leahy32471722015-04-20 15:20:28 -070019#include <console/console.h>
Lee Leahy77ff0b12015-05-05 15:07:29 -070020#include <cpu/cpu.h>
21#include <cpu/x86/smm.h>
Lee Leahy32471722015-04-20 15:20:28 -070022#include <device/device.h>
23#include <device/pci.h>
Lee Leahy77ff0b12015-05-05 15:07:29 -070024#include <soc/iomap.h>
Lee Leahy32471722015-04-20 15:20:28 -070025#include <soc/pm.h>
Lee Leahy77ff0b12015-05-05 15:07:29 -070026#include <soc/smm.h>
Lee Leahy32471722015-04-20 15:20:28 -070027#include <string.h>
Lee Leahy77ff0b12015-05-05 15:07:29 -070028
29/* Save settings which will be committed in SMI functions. */
30static uint32_t smm_save_params[SMM_SAVE_PARAM_COUNT];
31
Lee Leahy32471722015-04-20 15:20:28 -070032void smm_init(void)
33{
34}
35
Lee Leahy77ff0b12015-05-05 15:07:29 -070036void southcluster_smm_save_param(int param, uint32_t data)
37{
38 smm_save_params[param] = data;
39}
40
41void southcluster_smm_clear_state(void)
42{
43 uint32_t smi_en;
44
45 /* Log events from chipset before clearing */
46 southcluster_log_state();
47
48 printk(BIOS_DEBUG, "Initializing Southbridge SMI...");
49 printk(BIOS_SPEW, " pmbase = 0x%04x\n", get_pmbase());
50
51 smi_en = inl(get_pmbase() + SMI_EN);
52 if (smi_en & APMC_EN) {
53 printk(BIOS_INFO, "SMI# handler already enabled?\n");
54 return;
55 }
56
57 /* Dump and clear status registers */
58 clear_smi_status();
59 clear_pm1_status();
60 clear_tco_status();
61 clear_gpe_status();
62 clear_alt_status();
63 clear_pmc_status();
64}
65
66static void southcluster_smm_route_gpios(void)
67{
Lee Leahy32471722015-04-20 15:20:28 -070068 void *gpio_rout = (void *)(PMC_BASE_ADDRESS + GPIO_ROUT);
Lee Leahy77ff0b12015-05-05 15:07:29 -070069 const unsigned short alt_gpio_smi = ACPI_BASE_ADDRESS + ALT_GPIO_SMI;
70 uint32_t alt_gpio_reg = 0;
71 uint32_t route_reg = smm_save_params[SMM_SAVE_PARAM_GPIO_ROUTE];
72 int i;
73
74 printk(BIOS_DEBUG, "GPIO_ROUT = %08x\n", route_reg);
75
76 /* Start the routing for the specific gpios. */
77 write32(gpio_rout, route_reg);
78
79 /* Enable SMIs for the gpios that are set to trigger the SMI. */
80 for (i = 0; i < 16; i++) {
Lee Leahy32471722015-04-20 15:20:28 -070081 if ((route_reg & ROUTE_MASK) == ROUTE_SMI)
Lee Leahy77ff0b12015-05-05 15:07:29 -070082 alt_gpio_reg |= (1 << i);
Lee Leahy77ff0b12015-05-05 15:07:29 -070083 route_reg >>= 2;
84 }
85 printk(BIOS_DEBUG, "ALT_GPIO_SMI = %08x\n", alt_gpio_reg);
86
87 outl(alt_gpio_reg, alt_gpio_smi);
88}
89
90void southcluster_smm_enable_smi(void)
91{
92 uint16_t pm1_events = PWRBTN_EN | GBL_EN;
93
94 printk(BIOS_DEBUG, "Enabling SMIs.\n");
95 if (!smm_save_params[SMM_SAVE_PARAM_PCIE_WAKE_ENABLE])
96 pm1_events |= PCIEXPWAK_DIS;
97 enable_pm1(pm1_events);
98 disable_gpe(PME_B0_EN);
99
100 /* Set up the GPIO route. */
101 southcluster_smm_route_gpios();
102
Lee Leahy32471722015-04-20 15:20:28 -0700103 /*
104 * Enable SMI generation:
Lee Leahy77ff0b12015-05-05 15:07:29 -0700105 * - on APMC writes (io 0xb2)
106 * - on writes to SLP_EN (sleep states)
107 * - on writes to GBL_RLS (bios commands)
108 * No SMIs:
109 * - on TCO events
110 * - on microcontroller writes (io 0x62/0x66)
111 */
112 enable_smi(APMC_EN | SLP_SMI_EN | GBL_SMI_EN | EOS);
113}
114
115void smm_setup_structures(void *gnvs, void *tcg, void *smi1)
116{
117 /*
118 * Issue SMI to set the gnvs pointer in SMM.
119 * tcg and smi1 are unused.
120 *
121 * EAX = APM_CNT_GNVS_UPDATE
122 * EBX = gnvs pointer
123 * EDX = APM_CNT
124 */
125 asm volatile (
126 "outb %%al, %%dx\n\t"
127 : /* ignore result */
128 : "a" (APM_CNT_GNVS_UPDATE),
129 "b" ((uint32_t)gnvs),
130 "d" (APM_CNT)
131 );
132}