]> git.proxmox.com Git - mirror_edk2.git/blob - DuetPkg/AcpiResetDxe/Reset.c
Port AcpiResetDxe from EDK to EDKII to enable reset function on DUET above legacy...
[mirror_edk2.git] / DuetPkg / AcpiResetDxe / Reset.c
1 /*++ @file
2 Reset Architectural Protocol implementation.
3
4 Copyright (c) 2006 - 2010, Intel Corporation
5 All rights reserved. This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13 --*/
14
15 #include "Reset.h"
16
17 /**
18 Use ACPI method to reset the sytem. If fail, use legacy 8042 method to reset the system
19
20 @param[in] AcpiDescription Global variable to record reset info
21
22 **/
23 VOID
24 SystemReset (
25 IN EFI_ACPI_DESCRIPTION *AcpiDescription
26 )
27 {
28 UINT8 Dev;
29 UINT8 Func;
30 UINT8 Register;
31
32 if ((AcpiDescription->RESET_REG.Address != 0) &&
33 ((AcpiDescription->RESET_REG.AddressSpaceId == EFI_ACPI_3_0_SYSTEM_IO) ||
34 (AcpiDescription->RESET_REG.AddressSpaceId == EFI_ACPI_3_0_SYSTEM_MEMORY) ||
35 (AcpiDescription->RESET_REG.AddressSpaceId == EFI_ACPI_3_0_PCI_CONFIGURATION_SPACE))) {
36 //
37 // Use ACPI System Reset
38 //
39 switch (AcpiDescription->RESET_REG.AddressSpaceId) {
40 case EFI_ACPI_3_0_SYSTEM_IO:
41 IoWrite8 ((UINTN) AcpiDescription->RESET_REG.Address, AcpiDescription->RESET_VALUE);
42 break;
43 case EFI_ACPI_3_0_SYSTEM_MEMORY:
44 MmioWrite8 ((UINTN) AcpiDescription->RESET_REG.Address, AcpiDescription->RESET_VALUE);
45 break;
46 case EFI_ACPI_3_0_PCI_CONFIGURATION_SPACE:
47 Register = (UINT8) AcpiDescription->RESET_REG.Address;
48 Func = (UINT8) (RShiftU64 (AcpiDescription->RESET_REG.Address, 16) & 0x7);
49 Dev = (UINT8) (RShiftU64 (AcpiDescription->RESET_REG.Address, 32) & 0x1F);
50 PciWrite8 (PCI_LIB_ADDRESS (0, Dev, Func, Register), AcpiDescription->RESET_VALUE);
51 break;
52 }
53 }
54
55 //
56 // If system comes here, means ACPI reset fail, do Legacy System Reset, assume 8042 available
57 //
58 Register = 0xfe;
59 IoWrite8 (0x64, Register);
60
61 //
62 // System should reset now
63 //
64
65 return ;
66 }
67
68 /**
69 Use ACPI method to shutdown the sytem
70
71 @param[in] AcpiDescription Global variable to record reset info
72
73 @retval EFI_UNSUPPORTED Shutdown fails
74
75 **/
76 EFI_STATUS
77 SystemShutdown (
78 IN EFI_ACPI_DESCRIPTION *AcpiDescription
79 )
80 {
81 UINT16 Value;
82
83 //
84 // 1. Write SLP_TYPa
85 //
86 if ((AcpiDescription->PM1a_CNT_BLK.Address != 0) && (AcpiDescription->SLP_TYPa != 0)) {
87 switch (AcpiDescription->PM1a_CNT_BLK.AddressSpaceId) {
88 case EFI_ACPI_3_0_SYSTEM_IO:
89 Value = IoRead16 ((UINTN) AcpiDescription->PM1a_CNT_BLK.Address);
90 Value = (Value & 0xc3ff) | 0x2000 | (AcpiDescription->SLP_TYPa << 10);
91 IoWrite16 ((UINTN) AcpiDescription->PM1a_CNT_BLK.Address, Value);
92 break;
93 case EFI_ACPI_3_0_SYSTEM_MEMORY:
94 Value = MmioRead16 ((UINTN) AcpiDescription->PM1a_CNT_BLK.Address);
95 Value = (Value & 0xc3ff) | 0x2000 | (AcpiDescription->SLP_TYPa << 10);
96 MmioWrite16 ((UINTN) AcpiDescription->PM1a_CNT_BLK.Address, Value);
97 break;
98 }
99 }
100
101 //
102 // 2. Write SLP_TYPb
103 //
104 if ((AcpiDescription->PM1b_CNT_BLK.Address != 0) && (AcpiDescription->SLP_TYPb != 0)) {
105 switch (AcpiDescription->PM1b_CNT_BLK.AddressSpaceId) {
106 case EFI_ACPI_3_0_SYSTEM_IO:
107 Value = IoRead16 ((UINTN) AcpiDescription->PM1b_CNT_BLK.Address);
108 Value = (Value & 0xc3ff) | 0x2000 | (AcpiDescription->SLP_TYPb << 10);
109 IoWrite16 ((UINTN) AcpiDescription->PM1b_CNT_BLK.Address, Value);
110 break;
111 case EFI_ACPI_3_0_SYSTEM_MEMORY:
112 Value = MmioRead16 ((UINTN) AcpiDescription->PM1b_CNT_BLK.Address);
113 Value = (Value & 0xc3ff) | 0x2000 | (AcpiDescription->SLP_TYPb << 10);
114 MmioWrite16 ((UINTN) AcpiDescription->PM1b_CNT_BLK.Address, Value);
115 break;
116 }
117 }
118
119 //
120 // Done, if code runs here, mean not shutdown correctly
121 //
122 return EFI_UNSUPPORTED;
123 }
124
125 /**
126 Reset the system.
127
128 @param[in] ResetType Warm or cold
129 @param[in] ResetStatus Possible cause of reset
130 @param[in] DataSize Size of ResetData in bytes
131 @param[in] ResetData Optional Unicode string
132 @param[in] AcpiDescription Global variable to record reset info
133
134 **/
135 VOID
136 EFIAPI
137 AcpiResetSystem (
138 IN EFI_RESET_TYPE ResetType,
139 IN EFI_STATUS ResetStatus,
140 IN UINTN DataSize,
141 IN CHAR16 *ResetData, OPTIONAL
142 IN EFI_ACPI_DESCRIPTION *AcpiDescription
143 )
144 {
145 EFI_STATUS Status;
146
147 switch (ResetType) {
148 case EfiResetWarm:
149 case EfiResetCold:
150 SystemReset (AcpiDescription);
151 break;
152
153 case EfiResetShutdown:
154 Status = SystemShutdown (AcpiDescription);
155 if (EFI_ERROR (Status)) {
156 SystemReset (AcpiDescription);
157 }
158 break;
159
160 default:
161 return ;
162 }
163
164 //
165 // Given we should have reset getting here would be bad
166 //
167 ASSERT (FALSE);
168 }
169
170 BOOLEAN
171 GetAcpiDescription (
172 IN EFI_ACPI_DESCRIPTION *AcpiDescription
173 )
174 {
175 EFI_HOB_GUID_TYPE *HobAcpiDescription;
176 //
177 // Get AcpiDescription Hob
178 //
179 HobAcpiDescription = GetFirstGuidHob (&gEfiAcpiDescriptionGuid);
180 if (HobAcpiDescription == NULL) {
181 return FALSE;
182 }
183
184 //
185 // Copy it to Runtime Memory
186 //
187 ASSERT (sizeof (EFI_ACPI_DESCRIPTION) == GET_GUID_HOB_DATA_SIZE (HobAcpiDescription));
188 CopyMem (AcpiDescription, GET_GUID_HOB_DATA (HobAcpiDescription), sizeof (EFI_ACPI_DESCRIPTION));
189
190 DEBUG ((EFI_D_ERROR, "ACPI Reset Base - %lx\n", AcpiDescription->RESET_REG.Address));
191 DEBUG ((EFI_D_ERROR, "ACPI Reset Value - %02x\n", (UINTN)AcpiDescription->RESET_VALUE));
192 DEBUG ((EFI_D_ERROR, "IAPC support - %x\n", (UINTN)(AcpiDescription->IAPC_BOOT_ARCH)));
193 return TRUE;
194 }