]> git.proxmox.com Git - mirror_edk2.git/blob - QuarkSocPkg/QuarkNorthCluster/Smm/DxeSmm/QncSmmDispatcher/QNC/QNCSmmSx.c
QuarkSocPkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / QuarkSocPkg / QuarkNorthCluster / Smm / DxeSmm / QncSmmDispatcher / QNC / QNCSmmSx.c
1 /** @file
2 File to contain all the hardware specific stuff for the Smm Sx dispatch protocol.
3
4 Copyright (c) 2013-2015 Intel Corporation.
5
6 SPDX-License-Identifier: BSD-2-Clause-Patent
7
8
9 **/
10
11 //
12 // Include common header file for this module.
13 //
14 #include "CommonHeader.h"
15
16 #include "QNCSmmHelpers.h"
17
18 CONST QNC_SMM_SOURCE_DESC SX_SOURCE_DESC = {
19 QNC_SMM_NO_FLAGS,
20 {
21 {
22 {GPE_ADDR_TYPE, {R_QNC_GPE0BLK_SMIE}}, S_QNC_GPE0BLK_SMIE, N_QNC_GPE0BLK_SMIE_SLP
23 },
24 NULL_BIT_DESC_INITIALIZER
25 },
26 {
27 {
28 {GPE_ADDR_TYPE, {R_QNC_GPE0BLK_SMIS}}, S_QNC_GPE0BLK_SMIS, N_QNC_GPE0BLK_SMIS_SLP
29 }
30 }
31 };
32
33 VOID
34 SxGetContext(
35 IN DATABASE_RECORD *Record,
36 OUT QNC_SMM_CONTEXT *Context
37 )
38 {
39 UINT32 Pm1Cnt;
40
41 Pm1Cnt = IoRead32 (PcdGet16 (PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1C);
42
43 //
44 // By design, the context phase will always be ENTRY
45 //
46 Context->Sx.Phase = SxEntry;
47
48 //
49 // Map the PM1_CNT register's SLP_TYP bits to the context type
50 //
51 switch (Pm1Cnt & B_QNC_PM1BLK_PM1C_SLPTP) {
52
53 case V_S0:
54 Context->Sx.Type = SxS0;
55 break;
56
57 case V_S3:
58 Context->Sx.Type = SxS3;
59 break;
60
61 case V_S4:
62 Context->Sx.Type = SxS4;
63 break;
64
65 case V_S5:
66 Context->Sx.Type = SxS5;
67 break;
68
69 default:
70 ASSERT (FALSE);
71 break;
72 };
73 }
74
75 BOOLEAN
76 SxCmpContext (
77 IN QNC_SMM_CONTEXT *Context1,
78 IN QNC_SMM_CONTEXT *Context2
79 )
80 {
81 return (BOOLEAN)(Context1->Sx.Type == Context2->Sx.Type);
82 }
83
84 VOID
85 QNCSmmSxGoToSleep(
86 VOID
87 )
88 /*++
89
90 Routine Description:
91
92 When we get an SMI that indicates that we are transitioning to a sleep state,
93 we need to actually transition to that state. We do this by disabling the
94 "SMI on sleep enable" feature, which generates an SMI when the operating system
95 tries to put the system to sleep, and then physically putting the system to sleep.
96
97 Returns:
98
99 None.
100
101 --*/
102 {
103 UINT32 Pm1Cnt;
104
105 //
106 // Flush cache into memory before we go to sleep. It is necessary for S3 sleep
107 // because we may update memory in SMM Sx sleep handlers -- the updates are in cache now
108 //
109 AsmWbinvd();
110
111 //
112 // Disable SMIs
113 //
114 QNCSmmClearSource (&SX_SOURCE_DESC );
115 QNCSmmDisableSource (&SX_SOURCE_DESC);
116
117 //
118 // Clear Sleep Type Enable
119 //
120 IoAnd16 ((UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) + R_QNC_GPE0BLK_SMIE, (UINT16)(~B_QNC_GPE0BLK_SMIE_SLP));
121
122 // clear sleep SMI status
123 IoAnd16 ((UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) + R_QNC_GPE0BLK_SMIS, (UINT16)(S_QNC_GPE0BLK_SMIS));
124
125 //
126 // Now that SMIs are disabled, write to the SLP_EN bit again to trigger the sleep
127 //
128 Pm1Cnt = IoOr32 (PcdGet16 (PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1C, B_QNC_PM1BLK_PM1C_SLPEN);
129
130 //
131 // The system just went to sleep. If the sleep state was S1, then code execution will resume
132 // here when the system wakes up.
133 //
134 Pm1Cnt = IoRead32 (PcdGet16 (PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1C);
135 if ((Pm1Cnt & B_QNC_PM1BLK_PM1C_SCIEN) == 0) {
136 //
137 // An ACPI OS isn't present, clear the sleep information
138 //
139 Pm1Cnt &= ~B_QNC_PM1BLK_PM1C_SLPTP;
140 Pm1Cnt |= V_S0;
141
142 IoWrite32 (PcdGet16 (PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1C, Pm1Cnt);
143 }
144
145 QNCSmmClearSource (&SX_SOURCE_DESC);
146 QNCSmmEnableSource (&SX_SOURCE_DESC);
147 }