blob: 8cde3bf7f2e6bd051e10bebba54362c9911c1c02 [file] [log] [blame]
Angel Pons0612b272020-04-05 15:46:56 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Subrata Banik7bc4dc52018-05-17 18:40:32 +05302
Angel Pons24f46232021-04-17 12:08:15 +02003#define __SIMPLE_DEVICE__
4
Subrata Banik7bc4dc52018-05-17 18:40:32 +05305#include <arch/io.h>
Kyösti Mälkkif1b58b72019-03-01 13:43:02 +02006#include <device/pci_ops.h>
Subrata Banik7bc4dc52018-05-17 18:40:32 +05307#include <device/device.h>
8#include <device/pci.h>
9#include <device/pci_def.h>
10#include <intelblocks/pcr.h>
Michael Niewöhner2bd2be52020-03-03 20:47:01 +010011#include <intelblocks/pmclib.h>
Subrata Banik7bc4dc52018-05-17 18:40:32 +053012#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#define PCR_DMI_TCOBASE 0x2778
20/* Enable TCO I/O range decode. */
21#define TCOEN (1 << 1)
22
23/* SMBUS TCO base address. */
24#define TCOBASE 0x50
25#define TCOCTL 0x54
26#define TCO_BASE_EN (1 << 8)
27
28/* Get base address of TCO I/O registers. */
29static uint16_t tco_get_bar(void)
30{
31 return TCO_BASE_ADDRESS;
32}
33
34uint16_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
43void 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
52void tco_lockdown(void)
53{
54 uint16_t tcocnt;
55
56 /* TCO Lock down */
57 tcocnt = tco_read_reg(TCO1_CNT);
58 tcocnt |= TCO_LOCK;
59 tco_write_reg(TCO1_CNT, tcocnt);
60}
61
62uint32_t tco_reset_status(void)
63{
64 uint16_t tco1_sts;
65 uint16_t tco2_sts;
66
Subrata Banik7bc4dc52018-05-17 18:40:32 +053067 /* TCO Status 1 register */
68 tco1_sts = tco_read_reg(TCO1_STS);
Michael Niewöhner04b02062020-03-03 18:33:00 +010069 tco_write_reg(TCO1_STS, tco1_sts);
70
71 /* TCO Status 2 register */
72 tco2_sts = tco_read_reg(TCO2_STS);
73 tco_write_reg(TCO2_STS, tco2_sts | TCO_STS_SECOND_TO);
Subrata Banik7bc4dc52018-05-17 18:40:32 +053074
75 return (tco2_sts << 16) | tco1_sts;
76}
77
78/* Stop TCO timer */
79static void tco_timer_disable(void)
80{
81 uint16_t tcocnt;
82
83 /* Program TCO timer halt */
84 tcocnt = tco_read_reg(TCO1_CNT);
85 tcocnt |= TCO_TMR_HLT;
86 tco_write_reg(TCO1_CNT, tcocnt);
87}
88
Michael Niewöhner2bd2be52020-03-03 20:47:01 +010089/* Enable and initialize TCO intruder SMI */
90static void tco_intruder_smi_enable(void)
91{
92 uint16_t tcocnt;
93
94 /* Make TCO issue an SMI on INTRD_DET assertion */
95 tcocnt = tco_read_reg(TCO2_CNT);
96 tcocnt &= ~TCO_INTRD_SEL_MASK;
97 tcocnt |= TCO_INTRD_SEL_SMI;
98 tco_write_reg(TCO2_CNT, tcocnt);
99}
100
Subrata Banik7bc4dc52018-05-17 18:40:32 +0530101/* Enable TCO BAR using SMBUS TCO base to access TCO related register */
102static void tco_enable_bar(void)
103{
104 uint32_t reg32;
105 uint16_t tcobase;
Angel Pons24f46232021-04-17 12:08:15 +0200106 const pci_devfn_t dev = PCH_DEV_SMBUS;
Subrata Banik7bc4dc52018-05-17 18:40:32 +0530107
108 /* Disable TCO in SMBUS Device first before changing Base Address */
109 reg32 = pci_read_config32(dev, TCOCTL);
110 reg32 &= ~TCO_BASE_EN;
111 pci_write_config32(dev, TCOCTL, reg32);
112
113 /* Program TCO Base */
114 tcobase = tco_get_bar();
115 pci_write_config32(dev, TCOBASE, tcobase);
116
117 /* Enable TCO in SMBUS */
118 pci_write_config32(dev, TCOCTL, reg32 | TCO_BASE_EN);
119
120 /*
121 * Program "TCO Base Address" PCR[DMI] + 2778h[15:5, 1]
122 */
123 pcr_write32(PID_DMI, PCR_DMI_TCOBASE, tcobase | TCOEN);
124}
125
126/*
127 * Enable TCO BAR using SMBUS TCO base to access TCO related register
128 * also disable the timer.
129 */
130void tco_configure(void)
131{
Julius Wernercd49cce2019-03-05 16:53:33 -0800132 if (CONFIG(SOC_INTEL_COMMON_BLOCK_TCO_ENABLE_THROUGH_SMBUS))
Subrata Banik7bc4dc52018-05-17 18:40:32 +0530133 tco_enable_bar();
134
135 tco_timer_disable();
Michael Niewöhner2bd2be52020-03-03 20:47:01 +0100136
137 /* Enable intruder interrupt if TCO interrupts are enabled*/
138 if (CONFIG(SOC_INTEL_COMMON_BLOCK_SMM_TCO_ENABLE))
139 tco_intruder_smi_enable();
Subrata Banik7bc4dc52018-05-17 18:40:32 +0530140}