blob: 8ec24b67fe647468e2156262c98c06e154f43bc6 [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
3#include <arch/io.h>
Kyösti Mälkkif1b58b72019-03-01 13:43:02 +02004#include <device/pci_ops.h>
Subrata Banik7bc4dc52018-05-17 18:40:32 +05305#include <device/device.h>
6#include <device/pci.h>
7#include <device/pci_def.h>
8#include <intelblocks/pcr.h>
Michael Niewöhner2bd2be52020-03-03 20:47:01 +01009#include <intelblocks/pmclib.h>
Subrata Banik7bc4dc52018-05-17 18:40:32 +053010#include <intelblocks/tco.h>
11#include <soc/iomap.h>
12#include <soc/pci_devs.h>
13#include <soc/pcr_ids.h>
14#include <soc/pm.h>
15#include <soc/smbus.h>
16
17#define PCR_DMI_TCOBASE 0x2778
18/* Enable TCO I/O range decode. */
19#define TCOEN (1 << 1)
20
21/* SMBUS TCO base address. */
22#define TCOBASE 0x50
23#define TCOCTL 0x54
24#define TCO_BASE_EN (1 << 8)
25
26/* Get base address of TCO I/O registers. */
27static uint16_t tco_get_bar(void)
28{
29 return TCO_BASE_ADDRESS;
30}
31
32uint16_t tco_read_reg(uint16_t tco_reg)
33{
34 uint16_t tcobase;
35
36 tcobase = tco_get_bar();
37
38 return inw(tcobase + tco_reg);
39}
40
41void tco_write_reg(uint16_t tco_reg, uint16_t value)
42{
43 uint16_t tcobase;
44
45 tcobase = tco_get_bar();
46
47 outw(value, tcobase + tco_reg);
48}
49
50void tco_lockdown(void)
51{
52 uint16_t tcocnt;
53
54 /* TCO Lock down */
55 tcocnt = tco_read_reg(TCO1_CNT);
56 tcocnt |= TCO_LOCK;
57 tco_write_reg(TCO1_CNT, tcocnt);
58}
59
60uint32_t tco_reset_status(void)
61{
62 uint16_t tco1_sts;
63 uint16_t tco2_sts;
64
Subrata Banik7bc4dc52018-05-17 18:40:32 +053065 /* TCO Status 1 register */
66 tco1_sts = tco_read_reg(TCO1_STS);
Michael Niewöhner04b02062020-03-03 18:33:00 +010067 tco_write_reg(TCO1_STS, tco1_sts);
68
69 /* TCO Status 2 register */
70 tco2_sts = tco_read_reg(TCO2_STS);
71 tco_write_reg(TCO2_STS, tco2_sts | TCO_STS_SECOND_TO);
Subrata Banik7bc4dc52018-05-17 18:40:32 +053072
73 return (tco2_sts << 16) | tco1_sts;
74}
75
76/* Stop TCO timer */
77static void tco_timer_disable(void)
78{
79 uint16_t tcocnt;
80
81 /* Program TCO timer halt */
82 tcocnt = tco_read_reg(TCO1_CNT);
83 tcocnt |= TCO_TMR_HLT;
84 tco_write_reg(TCO1_CNT, tcocnt);
85}
86
Michael Niewöhner2bd2be52020-03-03 20:47:01 +010087/* Enable and initialize TCO intruder SMI */
88static void tco_intruder_smi_enable(void)
89{
90 uint16_t tcocnt;
91
92 /* Make TCO issue an SMI on INTRD_DET assertion */
93 tcocnt = tco_read_reg(TCO2_CNT);
94 tcocnt &= ~TCO_INTRD_SEL_MASK;
95 tcocnt |= TCO_INTRD_SEL_SMI;
96 tco_write_reg(TCO2_CNT, tcocnt);
97}
98
Subrata Banik7bc4dc52018-05-17 18:40:32 +053099/* Enable TCO BAR using SMBUS TCO base to access TCO related register */
100static void tco_enable_bar(void)
101{
102 uint32_t reg32;
103 uint16_t tcobase;
104#if defined(__SIMPLE_DEVICE__)
105 int devfn = PCH_DEVFN_SMBUS;
106 pci_devfn_t dev = PCI_DEV(0, PCI_SLOT(devfn), PCI_FUNC(devfn));
107#else
108 struct device *dev;
109 dev = PCH_DEV_SMBUS;
110#endif
111
112 /* Disable TCO in SMBUS Device first before changing Base Address */
113 reg32 = pci_read_config32(dev, TCOCTL);
114 reg32 &= ~TCO_BASE_EN;
115 pci_write_config32(dev, TCOCTL, reg32);
116
117 /* Program TCO Base */
118 tcobase = tco_get_bar();
119 pci_write_config32(dev, TCOBASE, tcobase);
120
121 /* Enable TCO in SMBUS */
122 pci_write_config32(dev, TCOCTL, reg32 | TCO_BASE_EN);
123
124 /*
125 * Program "TCO Base Address" PCR[DMI] + 2778h[15:5, 1]
126 */
127 pcr_write32(PID_DMI, PCR_DMI_TCOBASE, tcobase | TCOEN);
128}
129
130/*
131 * Enable TCO BAR using SMBUS TCO base to access TCO related register
132 * also disable the timer.
133 */
134void tco_configure(void)
135{
Julius Wernercd49cce2019-03-05 16:53:33 -0800136 if (CONFIG(SOC_INTEL_COMMON_BLOCK_TCO_ENABLE_THROUGH_SMBUS))
Subrata Banik7bc4dc52018-05-17 18:40:32 +0530137 tco_enable_bar();
138
139 tco_timer_disable();
Michael Niewöhner2bd2be52020-03-03 20:47:01 +0100140
141 /* Enable intruder interrupt if TCO interrupts are enabled*/
142 if (CONFIG(SOC_INTEL_COMMON_BLOCK_SMM_TCO_ENABLE))
143 tco_intruder_smi_enable();
Subrata Banik7bc4dc52018-05-17 18:40:32 +0530144}