aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/acpica/hwxface.c
diff options
context:
space:
mode:
authorBob Moore <robert.moore@intel.com>2009-06-23 21:44:06 -0400
committerLen Brown <len.brown@intel.com>2009-08-27 10:17:14 -0400
commitc6b5774caafa4c12b6019366e2fdaaff117e95a4 (patch)
tree04a9439010ba84fd2ab787d6d43dbcebe2020a1e /drivers/acpi/acpica/hwxface.c
parentf8d80cdf40fe4d2393159012b38ce9f85a488686 (diff)
ACPICA: Add 64-bit support to acpi_read and acpi_write
Needed by drivers for new ACPi tables. Internal versions of these functions still use 32-bit max transfers, in order to minimize disruption and stack use for the standard ACPI registers (FADT-based). Signed-off-by: Bob Moore <robert.moore@intel.com> Signed-off-by: Lin Ming <ming.m.lin@intel.com> Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/acpi/acpica/hwxface.c')
-rw-r--r--drivers/acpi/acpica/hwxface.c166
1 files changed, 99 insertions, 67 deletions
diff --git a/drivers/acpi/acpica/hwxface.c b/drivers/acpi/acpica/hwxface.c
index 9829979f2bdd..4ead85f29215 100644
--- a/drivers/acpi/acpica/hwxface.c
+++ b/drivers/acpi/acpica/hwxface.c
@@ -80,7 +80,7 @@ acpi_status acpi_reset(void)
80 80
81 /* Write the reset value to the reset register */ 81 /* Write the reset value to the reset register */
82 82
83 status = acpi_write(acpi_gbl_FADT.reset_value, reset_reg); 83 status = acpi_hw_write(acpi_gbl_FADT.reset_value, reset_reg);
84 return_ACPI_STATUS(status); 84 return_ACPI_STATUS(status);
85} 85}
86 86
@@ -97,67 +97,92 @@ ACPI_EXPORT_SYMBOL(acpi_reset)
97 * 97 *
98 * DESCRIPTION: Read from either memory or IO space. 98 * DESCRIPTION: Read from either memory or IO space.
99 * 99 *
100 * LIMITATIONS: <These limitations also apply to acpi_write>
101 * bit_width must be exactly 8, 16, 32, or 64.
102 * space_iD must be system_memory or system_iO.
103 * bit_offset and access_width are currently ignored, as there has
104 * not been a need to implement these.
105 *
100 ******************************************************************************/ 106 ******************************************************************************/
101acpi_status acpi_read(u32 *value, struct acpi_generic_address *reg) 107acpi_status acpi_read(u64 *return_value, struct acpi_generic_address *reg)
102{ 108{
109 u32 value;
103 u32 width; 110 u32 width;
104 u64 address; 111 u64 address;
105 acpi_status status; 112 acpi_status status;
106 113
107 ACPI_FUNCTION_NAME(acpi_read); 114 ACPI_FUNCTION_NAME(acpi_read);
108 115
109 /* 116 if (!return_value) {
110 * Must have a valid pointer to a GAS structure, and a non-zero address
111 * within.
112 */
113 if (!reg) {
114 return (AE_BAD_PARAMETER); 117 return (AE_BAD_PARAMETER);
115 } 118 }
116 119
117 /* Get a local copy of the address. Handles possible alignment issues */ 120 /* Validate contents of the GAS register. Allow 64-bit transfers */
118 121
119 ACPI_MOVE_64_TO_64(&address, &reg->address); 122 status = acpi_hw_validate_register(reg, 64, &address);
120 if (!address) { 123 if (ACPI_FAILURE(status)) {
121 return (AE_BAD_ADDRESS); 124 return (status);
122 } 125 }
123 126
124 /* Supported widths are 8/16/32 */
125
126 width = reg->bit_width; 127 width = reg->bit_width;
127 if ((width != 8) && (width != 16) && (width != 32)) { 128 if (width == 64) {
128 return (AE_SUPPORT); 129 width = 32; /* Break into two 32-bit transfers */
129 } 130 }
130 131
131 /* Initialize entire 32-bit return value to zero */ 132 /* Initialize entire 64-bit return value to zero */
132 133
133 *value = 0; 134 *return_value = 0;
135 value = 0;
134 136
135 /* 137 /*
136 * Two address spaces supported: Memory or IO. PCI_Config is 138 * Two address spaces supported: Memory or IO. PCI_Config is
137 * not supported here because the GAS structure is insufficient 139 * not supported here because the GAS structure is insufficient
138 */ 140 */
139 switch (reg->space_id) { 141 if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) {
140 case ACPI_ADR_SPACE_SYSTEM_MEMORY: 142 status = acpi_os_read_memory((acpi_physical_address)
143 address, &value, width);
144 if (ACPI_FAILURE(status)) {
145 return (status);
146 }
147 *return_value = value;
148
149 if (reg->bit_width == 64) {
141 150
142 status = acpi_os_read_memory((acpi_physical_address) address, 151 /* Read the top 32 bits */
143 value, width);
144 break;
145 152
146 case ACPI_ADR_SPACE_SYSTEM_IO: 153 status = acpi_os_read_memory((acpi_physical_address)
154 (address + 4), &value, 32);
155 if (ACPI_FAILURE(status)) {
156 return (status);
157 }
158 *return_value |= ((u64)value << 32);
159 }
160 } else { /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */
147 161
148 status = 162 status = acpi_hw_read_port((acpi_io_address)
149 acpi_hw_read_port((acpi_io_address) address, value, width); 163 address, &value, width);
150 break; 164 if (ACPI_FAILURE(status)) {
165 return (status);
166 }
167 *return_value = value;
151 168
152 default: 169 if (reg->bit_width == 64) {
153 ACPI_ERROR((AE_INFO, 170
154 "Unsupported address space: %X", reg->space_id)); 171 /* Read the top 32 bits */
155 return (AE_BAD_PARAMETER); 172
173 status = acpi_hw_read_port((acpi_io_address)
174 (address + 4), &value, 32);
175 if (ACPI_FAILURE(status)) {
176 return (status);
177 }
178 *return_value |= ((u64)value << 32);
179 }
156 } 180 }
157 181
158 ACPI_DEBUG_PRINT((ACPI_DB_IO, 182 ACPI_DEBUG_PRINT((ACPI_DB_IO,
159 "Read: %8.8X width %2d from %8.8X%8.8X (%s)\n", 183 "Read: %8.8X%8.8X width %2d from %8.8X%8.8X (%s)\n",
160 *value, width, ACPI_FORMAT_UINT64(address), 184 ACPI_FORMAT_UINT64(*return_value), reg->bit_width,
185 ACPI_FORMAT_UINT64(address),
161 acpi_ut_get_region_name(reg->space_id))); 186 acpi_ut_get_region_name(reg->space_id)));
162 187
163 return (status); 188 return (status);
@@ -169,7 +194,7 @@ ACPI_EXPORT_SYMBOL(acpi_read)
169 * 194 *
170 * FUNCTION: acpi_write 195 * FUNCTION: acpi_write
171 * 196 *
172 * PARAMETERS: Value - To be written 197 * PARAMETERS: Value - Value to be written
173 * Reg - GAS register structure 198 * Reg - GAS register structure
174 * 199 *
175 * RETURN: Status 200 * RETURN: Status
@@ -177,7 +202,7 @@ ACPI_EXPORT_SYMBOL(acpi_read)
177 * DESCRIPTION: Write to either memory or IO space. 202 * DESCRIPTION: Write to either memory or IO space.
178 * 203 *
179 ******************************************************************************/ 204 ******************************************************************************/
180acpi_status acpi_write(u32 value, struct acpi_generic_address *reg) 205acpi_status acpi_write(u64 value, struct acpi_generic_address *reg)
181{ 206{
182 u32 width; 207 u32 width;
183 u64 address; 208 u64 address;
@@ -185,54 +210,61 @@ acpi_status acpi_write(u32 value, struct acpi_generic_address *reg)
185 210
186 ACPI_FUNCTION_NAME(acpi_write); 211 ACPI_FUNCTION_NAME(acpi_write);
187 212
188 /* 213 /* Validate contents of the GAS register. Allow 64-bit transfers */
189 * Must have a valid pointer to a GAS structure, and a non-zero address
190 * within.
191 */
192 if (!reg) {
193 return (AE_BAD_PARAMETER);
194 }
195 214
196 /* Get a local copy of the address. Handles possible alignment issues */ 215 status = acpi_hw_validate_register(reg, 64, &address);
197 216 if (ACPI_FAILURE(status)) {
198 ACPI_MOVE_64_TO_64(&address, &reg->address); 217 return (status);
199 if (!address) {
200 return (AE_BAD_ADDRESS);
201 } 218 }
202 219
203 /* Supported widths are 8/16/32 */
204
205 width = reg->bit_width; 220 width = reg->bit_width;
206 if ((width != 8) && (width != 16) && (width != 32)) { 221 if (width == 64) {
207 return (AE_SUPPORT); 222 width = 32; /* Break into two 32-bit transfers */
208 } 223 }
209 224
210 /* 225 /*
211 * Two address spaces supported: Memory or IO. 226 * Two address spaces supported: Memory or IO. PCI_Config is
212 * PCI_Config is not supported here because the GAS struct is insufficient 227 * not supported here because the GAS structure is insufficient
213 */ 228 */
214 switch (reg->space_id) { 229 if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) {
215 case ACPI_ADR_SPACE_SYSTEM_MEMORY: 230 status = acpi_os_write_memory((acpi_physical_address)
216 231 address, ACPI_LODWORD(value),
217 status = acpi_os_write_memory((acpi_physical_address) address, 232 width);
218 value, width); 233 if (ACPI_FAILURE(status)) {
219 break; 234 return (status);
235 }
220 236
221 case ACPI_ADR_SPACE_SYSTEM_IO: 237 if (reg->bit_width == 64) {
238 status = acpi_os_write_memory((acpi_physical_address)
239 (address + 4),
240 ACPI_HIDWORD(value), 32);
241 if (ACPI_FAILURE(status)) {
242 return (status);
243 }
244 }
245 } else { /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */
222 246
223 status = acpi_hw_write_port((acpi_io_address) address, value, 247 status = acpi_hw_write_port((acpi_io_address)
248 address, ACPI_LODWORD(value),
224 width); 249 width);
225 break; 250 if (ACPI_FAILURE(status)) {
251 return (status);
252 }
226 253
227 default: 254 if (reg->bit_width == 64) {
228 ACPI_ERROR((AE_INFO, 255 status = acpi_hw_write_port((acpi_io_address)
229 "Unsupported address space: %X", reg->space_id)); 256 (address + 4),
230 return (AE_BAD_PARAMETER); 257 ACPI_HIDWORD(value), 32);
258 if (ACPI_FAILURE(status)) {
259 return (status);
260 }
261 }
231 } 262 }
232 263
233 ACPI_DEBUG_PRINT((ACPI_DB_IO, 264 ACPI_DEBUG_PRINT((ACPI_DB_IO,
234 "Wrote: %8.8X width %2d to %8.8X%8.8X (%s)\n", 265 "Wrote: %8.8X%8.8X width %2d to %8.8X%8.8X (%s)\n",
235 value, width, ACPI_FORMAT_UINT64(address), 266 ACPI_FORMAT_UINT64(value), reg->bit_width,
267 ACPI_FORMAT_UINT64(address),
236 acpi_ut_get_region_name(reg->space_id))); 268 acpi_ut_get_region_name(reg->space_id)));
237 269
238 return (status); 270 return (status);