xref: /aosp_15_r20/external/coreboot/src/soc/intel/common/block/smbus/tco.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
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 <intelblocks/gpmr.h>
10 #include <intelblocks/pcr.h>
11 #include <intelblocks/pmclib.h>
12 #include <intelblocks/tco.h>
13 #include <soc/iomap.h>
14 #include <soc/pci_devs.h>
15 #include <soc/pcr_ids.h>
16 #include <soc/pm.h>
17 #include <soc/smbus.h>
18 
19 /* SMBUS TCO base address. */
20 #define TCOBASE		0x50
21 #define TCOCTL		0x54
22 #define  TCO_BASE_EN		(1 << 8)
23 #define  TCO_BASE_LOCK		(1 << 0)
24 
25 #define TCO_TMR_MIN_VALUE	2
26 #define TCO_TMR_MAX_VALUE	1023
27 #define TCO_TMR_PERIOD_MS	600
28 
tco_get_bar(void)29 uint16_t tco_get_bar(void)
30 {
31 	return TCO_BASE_ADDRESS;
32 }
33 
tco_read_reg(uint16_t tco_reg)34 uint16_t tco_read_reg(uint16_t tco_reg)
35 {
36 	uint16_t tcobase;
37 
38 	tcobase = tco_get_bar();
39 
40 	return inw(tcobase + tco_reg);
41 }
42 
tco_write_reg(uint16_t tco_reg,uint16_t value)43 void tco_write_reg(uint16_t tco_reg, uint16_t value)
44 {
45 	uint16_t tcobase;
46 
47 	tcobase = tco_get_bar();
48 
49 	outw(value, tcobase + tco_reg);
50 }
51 
tco_lockdown(void)52 void tco_lockdown(void)
53 {
54 	uint16_t tcocnt;
55 	const pci_devfn_t dev = PCH_DEV_SMBUS;
56 
57 	/* TCO base address lockdown */
58 	pci_or_config32(dev, TCOCTL, TCO_BASE_LOCK);
59 
60 	/* TCO Lock down */
61 	tcocnt = tco_read_reg(TCO1_CNT);
62 	tcocnt |= TCO1_LOCK;
63 	tco_write_reg(TCO1_CNT, tcocnt);
64 }
65 
tco_reset_status(void)66 uint32_t tco_reset_status(void)
67 {
68 	uint16_t tco1_sts;
69 	uint16_t tco2_sts;
70 
71 	/* TCO Status 1 register */
72 	tco1_sts = tco_read_reg(TCO1_STS);
73 	tco_write_reg(TCO1_STS, tco1_sts);
74 
75 	/* TCO Status 2 register */
76 	tco2_sts = tco_read_reg(TCO2_STS);
77 	tco_write_reg(TCO2_STS, tco2_sts | TCO2_STS_SECOND_TO);
78 
79 	if (CONFIG(ACPI_WDAT_WDT))
80 		tco_write_reg(TCO_MESSAGE1, tco2_sts & TCO2_STS_SECOND_TO);
81 
82 	return (tco2_sts << 16) | tco1_sts;
83 }
84 
85 /* Stop TCO timer */
tco_timer_disable(void)86 static void tco_timer_disable(void)
87 {
88 	uint16_t tcocnt;
89 
90 	/* Program TCO timer halt */
91 	tcocnt = tco_read_reg(TCO1_CNT);
92 	tcocnt |= TCO1_TMR_HLT;
93 	tco_write_reg(TCO1_CNT, tcocnt);
94 }
95 
96 /* Enable and initialize TCO intruder SMI */
tco_intruder_smi_enable(void)97 static void tco_intruder_smi_enable(void)
98 {
99 	uint16_t tcocnt;
100 
101 	/* Make TCO issue an SMI on INTRD_DET assertion */
102 	tcocnt = tco_read_reg(TCO2_CNT);
103 	tcocnt &= ~TCO2_INTRD_SEL_MASK;
104 	tcocnt |= TCO2_INTRD_SEL_SMI;
105 	tco_write_reg(TCO2_CNT, tcocnt);
106 }
107 
108 /* Enable TCO BAR using SMBUS TCO base to access TCO related register */
tco_enable_bar(void)109 static void tco_enable_bar(void)
110 {
111 	uint32_t reg32;
112 	uint16_t tcobase;
113 	const pci_devfn_t dev = PCH_DEV_SMBUS;
114 
115 	/* Disable TCO in SMBUS Device first before changing Base Address */
116 	reg32 = pci_read_config32(dev, TCOCTL);
117 	reg32 &= ~TCO_BASE_EN;
118 	pci_write_config32(dev, TCOCTL, reg32);
119 
120 	/* Program TCO Base */
121 	tcobase = tco_get_bar();
122 	pci_write_config32(dev, TCOBASE, tcobase);
123 
124 	/* Enable TCO in SMBUS */
125 	pci_write_config32(dev, TCOCTL, reg32 | TCO_BASE_EN);
126 
127 	/* Program TCO Base Address */
128 	gpmr_write32(GPMR_TCOBASE, tcobase | GPMR_TCOEN);
129 }
130 
131 /*
132  * Enable TCO BAR using SMBUS TCO base to access TCO related register
133  * also disable the timer.
134  */
tco_configure(void)135 void tco_configure(void)
136 {
137 	if (CONFIG(SOC_INTEL_COMMON_BLOCK_TCO_ENABLE_THROUGH_SMBUS))
138 		tco_enable_bar();
139 
140 	tco_timer_disable();
141 
142 	/* Enable intruder interrupt if TCO interrupts are enabled*/
143 	if (CONFIG(SOC_INTEL_COMMON_BLOCK_SMM_TCO_ENABLE))
144 		tco_intruder_smi_enable();
145 }
146 
tco_get_timer_period(void)147 uint32_t tco_get_timer_period(void)
148 {
149 	return TCO_TMR_PERIOD_MS;
150 }
151 
tco_get_timer_min_value(void)152 uint32_t tco_get_timer_min_value(void)
153 {
154 	return TCO_TMR_MIN_VALUE;
155 }
156 
tco_get_timer_max_value(void)157 uint32_t tco_get_timer_max_value(void)
158 {
159 	return TCO_TMR_MAX_VALUE;
160 }
161