coreboot
coreboot is an Open Source project aimed at replacing the proprietary BIOS found in most computers.
tco.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #define __SIMPLE_DEVICE__
4 
5 #include <arch/io.h>
6 #include <device/pci_ops.h>
7 #include <device/device.h>
8 #include <device/pci.h>
9 #include <device/pci_def.h>
10 #include <intelblocks/gpmr.h>
11 #include <intelblocks/pcr.h>
12 #include <intelblocks/pmclib.h>
13 #include <intelblocks/tco.h>
14 #include <soc/iomap.h>
15 #include <soc/pci_devs.h>
16 #include <soc/pcr_ids.h>
17 #include <soc/pm.h>
18 #include <soc/smbus.h>
19 
20 /* SMBUS TCO base address. */
21 #define TCOBASE 0x50
22 #define TCOCTL 0x54
23 #define TCO_BASE_EN (1 << 8)
24 #define TCO_BASE_LOCK (1 << 0)
25 
26 /* Get base address of TCO I/O registers. */
27 static uint16_t tco_get_bar(void)
28 {
29  return TCO_BASE_ADDRESS;
30 }
31 
33 {
34  uint16_t tcobase;
35 
36  tcobase = tco_get_bar();
37 
38  return inw(tcobase + tco_reg);
39 }
40 
42 {
43  uint16_t tcobase;
44 
45  tcobase = tco_get_bar();
46 
47  outw(value, tcobase + tco_reg);
48 }
49 
50 void tco_lockdown(void)
51 {
52  uint16_t tcocnt;
53  const pci_devfn_t dev = PCH_DEV_SMBUS;
54 
55  /* TCO base address lockdown */
57 
58  /* TCO Lock down */
59  tcocnt = tco_read_reg(TCO1_CNT);
60  tcocnt |= TCO_LOCK;
61  tco_write_reg(TCO1_CNT, tcocnt);
62 }
63 
65 {
66  uint16_t tco1_sts;
67  uint16_t tco2_sts;
68 
69  /* TCO Status 1 register */
70  tco1_sts = tco_read_reg(TCO1_STS);
71  tco_write_reg(TCO1_STS, tco1_sts);
72 
73  /* TCO Status 2 register */
74  tco2_sts = tco_read_reg(TCO2_STS);
76 
77  return (tco2_sts << 16) | tco1_sts;
78 }
79 
80 /* Stop TCO timer */
81 static void tco_timer_disable(void)
82 {
83  uint16_t tcocnt;
84 
85  /* Program TCO timer halt */
86  tcocnt = tco_read_reg(TCO1_CNT);
87  tcocnt |= TCO_TMR_HLT;
88  tco_write_reg(TCO1_CNT, tcocnt);
89 }
90 
91 /* Enable and initialize TCO intruder SMI */
92 static void tco_intruder_smi_enable(void)
93 {
94  uint16_t tcocnt;
95 
96  /* Make TCO issue an SMI on INTRD_DET assertion */
97  tcocnt = tco_read_reg(TCO2_CNT);
98  tcocnt &= ~TCO_INTRD_SEL_MASK;
99  tcocnt |= TCO_INTRD_SEL_SMI;
100  tco_write_reg(TCO2_CNT, tcocnt);
101 }
102 
103 /* Enable TCO BAR using SMBUS TCO base to access TCO related register */
104 static void tco_enable_bar(void)
105 {
106  uint32_t reg32;
107  uint16_t tcobase;
108  const pci_devfn_t dev = PCH_DEV_SMBUS;
109 
110  /* Disable TCO in SMBUS Device first before changing Base Address */
111  reg32 = pci_read_config32(dev, TCOCTL);
112  reg32 &= ~TCO_BASE_EN;
113  pci_write_config32(dev, TCOCTL, reg32);
114 
115  /* Program TCO Base */
116  tcobase = tco_get_bar();
117  pci_write_config32(dev, TCOBASE, tcobase);
118 
119  /* Enable TCO in SMBUS */
120  pci_write_config32(dev, TCOCTL, reg32 | TCO_BASE_EN);
121 
122  /* Program TCO Base Address */
124 }
125 
126 /*
127  * Enable TCO BAR using SMBUS TCO base to access TCO related register
128  * also disable the timer.
129  */
130 void tco_configure(void)
131 {
132  if (CONFIG(SOC_INTEL_COMMON_BLOCK_TCO_ENABLE_THROUGH_SMBUS))
133  tco_enable_bar();
134 
136 
137  /* Enable intruder interrupt if TCO interrupts are enabled*/
138  if (CONFIG(SOC_INTEL_COMMON_BLOCK_SMM_TCO_ENABLE))
140 }
pte_t value
Definition: mmu.c:91
u16 inw(u16 port)
void outw(u16 val, u16 port)
@ CONFIG
Definition: dsi_common.h:201
void gpmr_write32(uint16_t offset, uint32_t val)
Definition: gpmr.c:15
static __always_inline void pci_or_config32(const struct device *dev, u16 reg, u32 ormask)
Definition: pci_ops.h:191
static __always_inline void pci_write_config32(const struct device *dev, u16 reg, u32 val)
Definition: pci_ops.h:76
static __always_inline u32 pci_read_config32(const struct device *dev, u16 reg)
Definition: pci_ops.h:58
#define TCO_BASE_ADDRESS
Definition: iomap.h:102
u32 pci_devfn_t
Definition: pci_type.h:8
#define GPMR_TCOBASE
Definition: pcr_gpmr.h:14
#define GPMR_TCOEN
Definition: pcr_gpmr.h:15
#define PCH_DEV_SMBUS
Definition: pci_devs.h:240
#define TCO_TMR_HLT
Definition: smbus.h:14
#define TCO_INTRD_SEL_SMI
Definition: smbus.h:17
#define TCO2_STS
Definition: smbus.h:9
#define TCO_STS_SECOND_TO
Definition: smbus.h:10
#define TCO1_CNT
Definition: smbus.h:12
#define TCO1_STS
Definition: smbus.h:7
#define TCO_INTRD_SEL_MASK
Definition: smbus.h:16
#define TCO_LOCK
Definition: smbus.h:13
#define TCO2_CNT
Definition: smbus.h:15
unsigned short uint16_t
Definition: stdint.h:11
unsigned int uint32_t
Definition: stdint.h:14
#define TCOBASE
Definition: tco.c:21
static void tco_timer_disable(void)
Definition: tco.c:81
uint16_t tco_read_reg(uint16_t tco_reg)
Definition: tco.c:32
void tco_lockdown(void)
Definition: tco.c:50
static void tco_enable_bar(void)
Definition: tco.c:104
void tco_configure(void)
Definition: tco.c:130
void tco_write_reg(uint16_t tco_reg, uint16_t value)
Definition: tco.c:41
#define TCO_BASE_EN
Definition: tco.c:23
uint32_t tco_reset_status(void)
Definition: tco.c:64
static void tco_intruder_smi_enable(void)
Definition: tco.c:92
#define TCOCTL
Definition: tco.c:22
#define TCO_BASE_LOCK
Definition: tco.c:24
static uint16_t tco_get_bar(void)
Definition: tco.c:27