blob: 80329541a824b73e3d67da9cff73e1f070e85e75 [file] [log] [blame]
Alexandru Gagniuc599d6682014-04-17 23:33:50 -05001/*
Martin Rothebace9f2018-05-26 18:56:17 -06002 * This file is part of the coreboot project.
Alexandru Gagniuc599d6682014-04-17 23:33:50 -05003 *
4 * Copyright (C) 2014 Alexandru Gagniuc <mr.nuke.me@gmail.com>
Martin Rothebace9f2018-05-26 18:56:17 -06005 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License, or (at your
9 * option) any later version.
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.
15 */
16
17/*
18 * SMM utilities used in both SMM and normal mode
Alexandru Gagniuc599d6682014-04-17 23:33:50 -050019 */
20
Michał Żygowskif3db2ae2019-11-24 13:26:10 +010021#include <amdblocks/acpimmio.h>
Alexandru Gagniuc599d6682014-04-17 23:33:50 -050022#include <console/console.h>
23
Michał Żygowskif3db2ae2019-11-24 13:26:10 +010024#include "smi.h"
25
Alexandru Gagniuc599d6682014-04-17 23:33:50 -050026#define HUDSON_SMI_ACPI_COMMAND 75
27
28static void configure_smi(uint8_t smi_num, uint8_t mode)
29{
30 uint8_t reg32_offset, bit_offset;
31 uint32_t reg32;
32
33 /* SMI sources range from [0:149] */
34 if (smi_num > 149) {
35 printk(BIOS_WARNING, "BUG: Invalid SMI: %u\n", smi_num);
36 return;
37 }
38
39 /* 16 sources per register, 2 bits per source; registers are 4 bytes */
40 reg32_offset = (smi_num / 16) * 4;
41 bit_offset = (smi_num % 16) * 2;
42
43 reg32 = smi_read32(SMI_REG_CONTROL0 + reg32_offset);
44 reg32 &= ~(0x3 << (bit_offset));
45 reg32 |= (mode & 0x3) << bit_offset;
46 smi_write32(SMI_REG_CONTROL0 + reg32_offset, reg32);
47}
48
49/**
50 * Configure generation of interrupts for given GEVENT pin
51 *
52 * @param gevent The GEVENT pin number. Valid values are 0 thru 23
53 * @param mode The type of event this pin should generate. Note that only
54 * SMI_MODE_SMI generates an SMI. SMI_MODE_DISABLE disables events.
55 * @param level SMI_LVL_LOW or SMI_LVL_HIGH
56 */
57void hudson_configure_gevent_smi(uint8_t gevent, uint8_t mode, uint8_t level)
58{
59 uint32_t reg32;
60 /* GEVENT pins range from [0:23] */
61 if (gevent > 23) {
62 printk(BIOS_WARNING, "BUG: Invalid GEVENT: %u\n", gevent);
63 return;
64 }
65
66 /* SMI0 source is GEVENT0 and so on */
67 configure_smi(gevent, mode);
68
69 /* And set set the trigger level */
70 reg32 = smi_read32(SMI_REG_SMITRIG0);
71 reg32 &= ~(1 << gevent);
72 reg32 |= (level & 0x1) << gevent;
73 smi_write32(SMI_REG_SMITRIG0, reg32);
74}
75
76/** Disable events from given GEVENT pin */
77void hudson_disable_gevent_smi(uint8_t gevent)
78{
79 /* GEVENT pins range from [0:23] */
80 if (gevent > 23) {
81 printk(BIOS_WARNING, "BUG: Invalid GEVENT: %u\n", gevent);
82 return;
83 }
84
85 /* SMI0 source is GEVENT0 and so on */
86 configure_smi(gevent, SMI_MODE_DISABLE);
87}
88
89/** Enable SMIs on writes to ACPI SMI command port */
90void hudson_enable_acpi_cmd_smi(void)
91{
92 configure_smi(HUDSON_SMI_ACPI_COMMAND, SMI_MODE_SMI);
93}