hwregs.c 19.8 KB
Newer Older
Linus Torvalds's avatar
Linus Torvalds committed
1 2 3 4 5

/*******************************************************************************
 *
 * Module Name: hwregs - Read/write access functions for the various ACPI
 *                       control and status registers.
Andy Grover's avatar
Andy Grover committed
6
 *              $Revision: 120 $
Linus Torvalds's avatar
Linus Torvalds committed
7 8 9 10
 *
 ******************************************************************************/

/*
Andy Grover's avatar
Andy Grover committed
11
 *  Copyright (C) 2000 - 2002, R. Byron Moore
Linus Torvalds's avatar
Linus Torvalds committed
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */


#include "acpi.h"
#include "achware.h"
#include "acnamesp.h"

Linus Torvalds's avatar
Linus Torvalds committed
33
#define _COMPONENT          ACPI_HARDWARE
Andy Grover's avatar
Andy Grover committed
34
	 ACPI_MODULE_NAME    ("hwregs")
Linus Torvalds's avatar
Linus Torvalds committed
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51


/*******************************************************************************
 *
 * FUNCTION:    Acpi_hw_clear_acpi_status
 *
 * PARAMETERS:  none
 *
 * RETURN:      none
 *
 * DESCRIPTION: Clears all fixed and general purpose status bits
 *
 ******************************************************************************/

void
acpi_hw_clear_acpi_status (void)
{
Andy Grover's avatar
Andy Grover committed
52 53 54
	NATIVE_UINT             i;
	NATIVE_UINT             gpe_block;
	acpi_status             status;
Linus Torvalds's avatar
Linus Torvalds committed
55 56


Andy Grover's avatar
Andy Grover committed
57
	ACPI_FUNCTION_TRACE ("Hw_clear_acpi_status");
Linus Torvalds's avatar
Linus Torvalds committed
58 59 60


	ACPI_DEBUG_PRINT ((ACPI_DB_IO, "About to write %04X to %04X\n",
Andy Grover's avatar
Andy Grover committed
61
		ACPI_BITMASK_ALL_FIXED_STATUS,
Linus Torvalds's avatar
Linus Torvalds committed
62 63 64
		(u16) ACPI_GET_ADDRESS (acpi_gbl_FADT->Xpm1a_evt_blk.address)));


Andy Grover's avatar
Andy Grover committed
65 66 67 68
	status = acpi_ut_acquire_mutex (ACPI_MTX_HARDWARE);
	if (ACPI_FAILURE (status)) {
		return_VOID;
	}
Linus Torvalds's avatar
Linus Torvalds committed
69

Andy Grover's avatar
Andy Grover committed
70 71
	acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK, ACPI_REGISTER_PM1_STATUS,
			ACPI_BITMASK_ALL_FIXED_STATUS);
Linus Torvalds's avatar
Linus Torvalds committed
72

Andy Grover's avatar
Andy Grover committed
73
	/* Clear the fixed events */
Linus Torvalds's avatar
Linus Torvalds committed
74 75

	if (ACPI_VALID_ADDRESS (acpi_gbl_FADT->Xpm1b_evt_blk.address)) {
Linus Torvalds's avatar
Linus Torvalds committed
76 77
		acpi_os_write_port ((ACPI_IO_ADDRESS)
			ACPI_GET_ADDRESS (acpi_gbl_FADT->Xpm1b_evt_blk.address),
Andy Grover's avatar
Andy Grover committed
78
			ACPI_BITMASK_ALL_FIXED_STATUS, 16);
Linus Torvalds's avatar
Linus Torvalds committed
79 80
	}

Andy Grover's avatar
Andy Grover committed
81
	/* Clear the GPE Bits */
Linus Torvalds's avatar
Linus Torvalds committed
82

Andy Grover's avatar
Andy Grover committed
83 84 85 86
	for (gpe_block = 0; gpe_block < ACPI_MAX_GPE_BLOCKS; gpe_block++) {
		for (i = 0; i < acpi_gbl_gpe_block_info[gpe_block].register_count; i++) {
			acpi_os_write_port ((ACPI_IO_ADDRESS)
				(acpi_gbl_gpe_block_info[gpe_block].block_address + i),
Linus Torvalds's avatar
Linus Torvalds committed
87
				0xFF, 8);
Linus Torvalds's avatar
Linus Torvalds committed
88 89 90
		}
	}

Andy Grover's avatar
Andy Grover committed
91
	(void) acpi_ut_release_mutex (ACPI_MTX_HARDWARE);
Linus Torvalds's avatar
Linus Torvalds committed
92
	return_VOID;
Linus Torvalds's avatar
Linus Torvalds committed
93 94 95 96 97
}


/*******************************************************************************
 *
Andy Grover's avatar
Andy Grover committed
98
 * FUNCTION:    Acpi_hw_get_sleep_type_data
Linus Torvalds's avatar
Linus Torvalds committed
99
 *
Andy Grover's avatar
Andy Grover committed
100 101 102
 * PARAMETERS:  Sleep_state         - Numeric sleep state
 *              *Sleep_type_a        - Where SLP_TYPa is returned
 *              *Sleep_type_b        - Where SLP_TYPb is returned
Linus Torvalds's avatar
Linus Torvalds committed
103 104 105
 *
 * RETURN:      Status - ACPI status
 *
Andy Grover's avatar
Andy Grover committed
106 107
 * DESCRIPTION: Obtain the SLP_TYPa and SLP_TYPb values for the requested sleep
 *              state.
Linus Torvalds's avatar
Linus Torvalds committed
108 109 110
 *
 ******************************************************************************/

Linus Torvalds's avatar
Linus Torvalds committed
111
acpi_status
Andy Grover's avatar
Andy Grover committed
112
acpi_hw_get_sleep_type_data (
Linus Torvalds's avatar
Linus Torvalds committed
113
	u8                      sleep_state,
Andy Grover's avatar
Andy Grover committed
114 115
	u8                      *sleep_type_a,
	u8                      *sleep_type_b)
Linus Torvalds's avatar
Linus Torvalds committed
116
{
Linus Torvalds's avatar
Linus Torvalds committed
117 118 119 120
	acpi_status             status = AE_OK;
	acpi_operand_object     *obj_desc;


Andy Grover's avatar
Andy Grover committed
121
	ACPI_FUNCTION_TRACE ("Hw_get_sleep_type_data");
Linus Torvalds's avatar
Linus Torvalds committed
122 123 124 125 126 127


	/*
	 *  Validate parameters
	 */
	if ((sleep_state > ACPI_S_STATES_MAX) ||
Andy Grover's avatar
Andy Grover committed
128
		!sleep_type_a || !sleep_type_b) {
Linus Torvalds's avatar
Linus Torvalds committed
129
		return_ACPI_STATUS (AE_BAD_PARAMETER);
Linus Torvalds's avatar
Linus Torvalds committed
130 131 132 133 134
	}

	/*
	 *  Acpi_evaluate the namespace object containing the values for this state
	 */
Linus Torvalds's avatar
Linus Torvalds committed
135 136
	status = acpi_ns_evaluate_by_name ((NATIVE_CHAR *) acpi_gbl_db_sleep_states[sleep_state],
			  NULL, &obj_desc);
Linus Torvalds's avatar
Linus Torvalds committed
137
	if (ACPI_FAILURE (status)) {
Linus Torvalds's avatar
Linus Torvalds committed
138
		return_ACPI_STATUS (status);
Linus Torvalds's avatar
Linus Torvalds committed
139 140 141
	}

	if (!obj_desc) {
Andy Grover's avatar
Andy Grover committed
142
		ACPI_REPORT_ERROR (("Missing Sleep State object\n"));
Linus Torvalds's avatar
Linus Torvalds committed
143
		return_ACPI_STATUS (AE_NOT_EXIST);
Linus Torvalds's avatar
Linus Torvalds committed
144 145 146 147 148 149 150 151
	}

	/*
	 *  We got something, now ensure it is correct.  The object must
	 *  be a package and must have at least 2 numeric values as the
	 *  two elements
	 */

Linus Torvalds's avatar
Linus Torvalds committed
152
	/* Even though Acpi_evaluate_object resolves package references,
Andy Grover's avatar
Andy Grover committed
153
	 * Ns_evaluate doesn't. So, we do it here.
Linus Torvalds's avatar
Linus Torvalds committed
154 155
	 */
	status = acpi_ut_resolve_package_references(obj_desc);
Linus Torvalds's avatar
Linus Torvalds committed
156 157 158 159

	if (obj_desc->package.count < 2) {
		/* Must have at least two elements */

Andy Grover's avatar
Andy Grover committed
160 161
		ACPI_REPORT_ERROR (("Sleep State package does not have at least two elements\n"));
		status = AE_AML_NO_OPERAND;
Linus Torvalds's avatar
Linus Torvalds committed
162
	}
Andy Grover's avatar
Andy Grover committed
163 164
	else if (((obj_desc->package.elements[0])->common.type != ACPI_TYPE_INTEGER) ||
			 ((obj_desc->package.elements[1])->common.type != ACPI_TYPE_INTEGER)) {
Linus Torvalds's avatar
Linus Torvalds committed
165 166
		/* Must have two  */

Andy Grover's avatar
Andy Grover committed
167 168
		ACPI_REPORT_ERROR (("Sleep State package elements are not both of type Number\n"));
		status = AE_AML_OPERAND_TYPE;
Linus Torvalds's avatar
Linus Torvalds committed
169 170 171 172 173
	}
	else {
		/*
		 *  Valid _Sx_ package size, type, and value
		 */
Andy Grover's avatar
Andy Grover committed
174 175
		*sleep_type_a = (u8) (obj_desc->package.elements[0])->integer.value;
		*sleep_type_b = (u8) (obj_desc->package.elements[1])->integer.value;
Linus Torvalds's avatar
Linus Torvalds committed
176 177
	}

Linus Torvalds's avatar
Linus Torvalds committed
178 179 180 181
	if (ACPI_FAILURE (status)) {
		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Bad Sleep object %p type %X\n",
			obj_desc, obj_desc->common.type));
	}
Linus Torvalds's avatar
Linus Torvalds committed
182

Linus Torvalds's avatar
Linus Torvalds committed
183
	acpi_ut_remove_reference (obj_desc);
Linus Torvalds's avatar
Linus Torvalds committed
184
	return_ACPI_STATUS (status);
Linus Torvalds's avatar
Linus Torvalds committed
185 186 187 188 189
}


/*******************************************************************************
 *
Andy Grover's avatar
Andy Grover committed
190
 * FUNCTION:    Acpi_hw_get_register_bit_mask
Linus Torvalds's avatar
Linus Torvalds committed
191
 *
Andy Grover's avatar
Andy Grover committed
192
 * PARAMETERS:  Register_id     - index of ACPI Register to access
Linus Torvalds's avatar
Linus Torvalds committed
193
 *
Andy Grover's avatar
Andy Grover committed
194
 * RETURN:      The bit mask to be used when accessing the register
Linus Torvalds's avatar
Linus Torvalds committed
195
 *
Andy Grover's avatar
Andy Grover committed
196
 * DESCRIPTION: Map Register_id into a register bit mask.
Linus Torvalds's avatar
Linus Torvalds committed
197 198 199
 *
 ******************************************************************************/

Andy Grover's avatar
Andy Grover committed
200 201 202
ACPI_BIT_REGISTER_INFO *
acpi_hw_get_bit_register_info (
	u32                     register_id)
Linus Torvalds's avatar
Linus Torvalds committed
203
{
Andy Grover's avatar
Andy Grover committed
204
	ACPI_FUNCTION_NAME ("Hw_get_bit_register_info");
Linus Torvalds's avatar
Linus Torvalds committed
205 206


Andy Grover's avatar
Andy Grover committed
207 208 209 210
	if (register_id > ACPI_BITREG_MAX) {
		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Invalid Bit_register ID: %X\n", register_id));
		return (NULL);
	}
Linus Torvalds's avatar
Linus Torvalds committed
211

Andy Grover's avatar
Andy Grover committed
212 213
	return (&acpi_gbl_bit_register_info[register_id]);
}
Linus Torvalds's avatar
Linus Torvalds committed
214

Linus Torvalds's avatar
Linus Torvalds committed
215

Andy Grover's avatar
Andy Grover committed
216 217 218 219 220 221 222 223 224 225 226 227 228
/*******************************************************************************
 *
 * FUNCTION:    Acpi_hw_bit_register_read
 *
 * PARAMETERS:  Register_id     - index of ACPI Register to access
 *              Use_lock        - Lock the hardware
 *
 * RETURN:      Value is read from specified Register.  Value returned is
 *              normalized to bit0 (is shifted all the way right)
 *
 * DESCRIPTION: ACPI Bit_register read function.
 *
 ******************************************************************************/
Linus Torvalds's avatar
Linus Torvalds committed
229

Andy Grover's avatar
Andy Grover committed
230 231 232 233 234 235 236
u32
acpi_hw_bit_register_read (
	u32                     register_id,
	u32                     flags)
{
	u32                     register_value = 0;
	ACPI_BIT_REGISTER_INFO  *bit_reg_info;
Linus Torvalds's avatar
Linus Torvalds committed
237 238


Andy Grover's avatar
Andy Grover committed
239
	ACPI_FUNCTION_TRACE ("Hw_bit_register_read");
Linus Torvalds's avatar
Linus Torvalds committed
240 241


Andy Grover's avatar
Andy Grover committed
242 243 244 245 246
	if (flags & ACPI_MTX_LOCK) {
		if (ACPI_FAILURE (acpi_ut_acquire_mutex (ACPI_MTX_HARDWARE))) {
			return_VALUE (0);
		}
	}
Linus Torvalds's avatar
Linus Torvalds committed
247

Andy Grover's avatar
Andy Grover committed
248
	/* Get the info structure corresponding to the requested ACPI Register */
Linus Torvalds's avatar
Linus Torvalds committed
249

Andy Grover's avatar
Andy Grover committed
250 251 252 253
	bit_reg_info = acpi_hw_get_bit_register_info (register_id);
	if (!bit_reg_info) {
		return_ACPI_STATUS (AE_BAD_PARAMETER);
	}
Linus Torvalds's avatar
Linus Torvalds committed
254

Andy Grover's avatar
Andy Grover committed
255
	register_value = acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK, bit_reg_info->parent_register);
Linus Torvalds's avatar
Linus Torvalds committed
256

Andy Grover's avatar
Andy Grover committed
257 258 259
	if (flags & ACPI_MTX_LOCK) {
		(void) acpi_ut_release_mutex (ACPI_MTX_HARDWARE);
	}
Linus Torvalds's avatar
Linus Torvalds committed
260

Andy Grover's avatar
Andy Grover committed
261
	/* Normalize the value that was read */
Linus Torvalds's avatar
Linus Torvalds committed
262

Andy Grover's avatar
Andy Grover committed
263
	register_value = ((register_value & bit_reg_info->access_bit_mask) >> bit_reg_info->bit_position);
Linus Torvalds's avatar
Linus Torvalds committed
264

Andy Grover's avatar
Andy Grover committed
265 266 267
	ACPI_DEBUG_PRINT ((ACPI_DB_IO, "ACPI Register_read: got %X\n", register_value));
	return_VALUE (register_value);
}
Linus Torvalds's avatar
Linus Torvalds committed
268 269


Andy Grover's avatar
Andy Grover committed
270 271 272 273 274 275 276 277 278 279 280 281 282 283 284
/*******************************************************************************
 *
 * FUNCTION:    Acpi_hw_bit_register_write
 *
 * PARAMETERS:  Register_id     - ID of ACPI Bit_register to access
 *              Value           - (only used on write) value to write to the
 *                                Register, NOT pre-normalized to the bit pos.
 *              Flags           - Lock the hardware or not
 *
 * RETURN:      Value written to from specified Register.  This value
 *              is shifted all the way right.
 *
 * DESCRIPTION: ACPI Bit Register write function.
 *
 ******************************************************************************/
Linus Torvalds's avatar
Linus Torvalds committed
285

Andy Grover's avatar
Andy Grover committed
286 287 288 289 290 291 292 293
u32
acpi_hw_bit_register_write (
	u32                     register_id,
	u32                     value,
	u32                     flags)
{
	u32                     register_value = 0;
	ACPI_BIT_REGISTER_INFO  *bit_reg_info;
Linus Torvalds's avatar
Linus Torvalds committed
294 295


Andy Grover's avatar
Andy Grover committed
296
	ACPI_FUNCTION_TRACE_U32 ("Hw_bit_register_write", register_id);
Linus Torvalds's avatar
Linus Torvalds committed
297 298


Andy Grover's avatar
Andy Grover committed
299 300 301
	if (flags & ACPI_MTX_LOCK) {
		if (ACPI_FAILURE (acpi_ut_acquire_mutex (ACPI_MTX_HARDWARE))) {
			return_VALUE (0);
Linus Torvalds's avatar
Linus Torvalds committed
302
		}
Andy Grover's avatar
Andy Grover committed
303
	}
Linus Torvalds's avatar
Linus Torvalds committed
304

Andy Grover's avatar
Andy Grover committed
305
	/* Get the info structure corresponding to the requested ACPI Register */
Linus Torvalds's avatar
Linus Torvalds committed
306

Andy Grover's avatar
Andy Grover committed
307 308 309 310
	bit_reg_info = acpi_hw_get_bit_register_info (register_id);
	if (!bit_reg_info) {
		return_ACPI_STATUS (AE_BAD_PARAMETER);
	}
Linus Torvalds's avatar
Linus Torvalds committed
311

Andy Grover's avatar
Andy Grover committed
312
	/* Always do a register read first so we can insert the new bits  */
Linus Torvalds's avatar
Linus Torvalds committed
313

Andy Grover's avatar
Andy Grover committed
314
	register_value = acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK, bit_reg_info->parent_register);
Linus Torvalds's avatar
Linus Torvalds committed
315

Andy Grover's avatar
Andy Grover committed
316 317 318 319 320 321 322 323 324
	/*
	 * Decode the Register ID
	 * Register id = Register block id | bit id
	 *
	 * Check bit id to fine locate Register offset.
	 * Check Mask to determine Register offset, and then read-write.
	 */
	switch (bit_reg_info->parent_register) {
	case ACPI_REGISTER_PM1_STATUS:
Linus Torvalds's avatar
Linus Torvalds committed
325

Andy Grover's avatar
Andy Grover committed
326 327 328 329 330 331 332 333 334 335 336 337 338
		/*
		 * Status Registers are different from the rest.  Clear by
		 * writing 1, writing 0 has no effect.  So, the only relevent
		 * information is the single bit we're interested in, all others should
		 * be written as 0 so they will be left unchanged
		 */
		value = ACPI_REGISTER_PREPARE_BITS (value, bit_reg_info->bit_position, bit_reg_info->access_bit_mask);
		if (value) {
			acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK, ACPI_REGISTER_PM1_STATUS,
				(u16) value);
			register_value = 0;
		}
		break;
Linus Torvalds's avatar
Linus Torvalds committed
339 340


Andy Grover's avatar
Andy Grover committed
341
	case ACPI_REGISTER_PM1_ENABLE:
Linus Torvalds's avatar
Linus Torvalds committed
342

Andy Grover's avatar
Andy Grover committed
343
		ACPI_REGISTER_INSERT_VALUE (register_value, bit_reg_info->bit_position, bit_reg_info->access_bit_mask, value);
Linus Torvalds's avatar
Linus Torvalds committed
344

Andy Grover's avatar
Andy Grover committed
345 346
		acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK, ACPI_REGISTER_PM1_ENABLE, (u16) register_value);
		break;
Linus Torvalds's avatar
Linus Torvalds committed
347 348


Andy Grover's avatar
Andy Grover committed
349
	case ACPI_REGISTER_PM1_CONTROL:
Linus Torvalds's avatar
Linus Torvalds committed
350 351 352 353

		/*
		 * Read the PM1 Control register.
		 * Note that at this level, the fact that there are actually TWO
Andy Grover's avatar
Andy Grover committed
354
		 * registers (A and B - and that B may not exist) is abstracted.
Linus Torvalds's avatar
Linus Torvalds committed
355
		 */
Linus Torvalds's avatar
Linus Torvalds committed
356 357
		ACPI_DEBUG_PRINT ((ACPI_DB_IO, "PM1 control: Read %X\n", register_value));

Andy Grover's avatar
Andy Grover committed
358
		ACPI_REGISTER_INSERT_VALUE (register_value, bit_reg_info->bit_position, bit_reg_info->access_bit_mask, value);
Linus Torvalds's avatar
Linus Torvalds committed
359

Andy Grover's avatar
Andy Grover committed
360 361 362
		acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK, register_id,
				(u16) register_value);
		break;
Linus Torvalds's avatar
Linus Torvalds committed
363 364


Andy Grover's avatar
Andy Grover committed
365
	case ACPI_REGISTER_PM2_CONTROL:
Linus Torvalds's avatar
Linus Torvalds committed
366

Andy Grover's avatar
Andy Grover committed
367
		register_value = acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK, ACPI_REGISTER_PM2_CONTROL);
Linus Torvalds's avatar
Linus Torvalds committed
368

Linus Torvalds's avatar
Linus Torvalds committed
369
		ACPI_DEBUG_PRINT ((ACPI_DB_IO, "PM2 control: Read %X from %8.8X%8.8X\n",
Andy Grover's avatar
Andy Grover committed
370 371
			register_value, ACPI_HIDWORD (acpi_gbl_FADT->Xpm2_cnt_blk.address),
			ACPI_LODWORD (acpi_gbl_FADT->Xpm2_cnt_blk.address)));
Linus Torvalds's avatar
Linus Torvalds committed
372

Andy Grover's avatar
Andy Grover committed
373
		ACPI_REGISTER_INSERT_VALUE (register_value, bit_reg_info->bit_position, bit_reg_info->access_bit_mask, value);
Linus Torvalds's avatar
Linus Torvalds committed
374

Andy Grover's avatar
Andy Grover committed
375
		ACPI_DEBUG_PRINT ((ACPI_DB_IO, "About to write %04X to %8.8X%8.8X\n",
Linus Torvalds's avatar
Linus Torvalds committed
376
			register_value,
Andy Grover's avatar
Andy Grover committed
377 378
			ACPI_HIDWORD (acpi_gbl_FADT->Xpm2_cnt_blk.address),
			ACPI_LODWORD (acpi_gbl_FADT->Xpm2_cnt_blk.address)));
Linus Torvalds's avatar
Linus Torvalds committed
379

Andy Grover's avatar
Andy Grover committed
380 381
		acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK,
				   ACPI_REGISTER_PM2_CONTROL, (u8) (register_value));
Linus Torvalds's avatar
Linus Torvalds committed
382 383 384 385 386 387 388
		break;


	default:
		break;
	}

Andy Grover's avatar
Andy Grover committed
389 390
	if (flags & ACPI_MTX_LOCK) {
		(void) acpi_ut_release_mutex (ACPI_MTX_HARDWARE);
Linus Torvalds's avatar
Linus Torvalds committed
391 392
	}

Andy Grover's avatar
Andy Grover committed
393
	/* Normalize the value that was read */
Linus Torvalds's avatar
Linus Torvalds committed
394

Andy Grover's avatar
Andy Grover committed
395
	register_value = ((register_value & bit_reg_info->access_bit_mask) >> bit_reg_info->bit_position);
Linus Torvalds's avatar
Linus Torvalds committed
396

Andy Grover's avatar
Andy Grover committed
397
	ACPI_DEBUG_PRINT ((ACPI_DB_IO, "ACPI Register_write actual %X\n", register_value));
Linus Torvalds's avatar
Linus Torvalds committed
398
	return_VALUE (register_value);
Linus Torvalds's avatar
Linus Torvalds committed
399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420
}


/******************************************************************************
 *
 * FUNCTION:    Acpi_hw_register_read
 *
 * PARAMETERS:  Use_lock               - Mutex hw access.
 *              Register_id            - Register_iD + Offset.
 *
 * RETURN:      Value read or written.
 *
 * DESCRIPTION: Acpi register read function.  Registers are read at the
 *              given offset.
 *
 ******************************************************************************/

u32
acpi_hw_register_read (
	u8                      use_lock,
	u32                     register_id)
{
Linus Torvalds's avatar
Linus Torvalds committed
421
	u32                     value = 0;
Linus Torvalds's avatar
Linus Torvalds committed
422 423
	u32                     bank_offset;

Linus Torvalds's avatar
Linus Torvalds committed
424

Andy Grover's avatar
Andy Grover committed
425
	ACPI_FUNCTION_TRACE ("Hw_register_read");
Linus Torvalds's avatar
Linus Torvalds committed
426 427


Linus Torvalds's avatar
Linus Torvalds committed
428
	if (ACPI_MTX_LOCK == use_lock) {
Andy Grover's avatar
Andy Grover committed
429 430 431
		if (ACPI_FAILURE (acpi_ut_acquire_mutex (ACPI_MTX_HARDWARE))) {
			return_VALUE (0);
		}
Linus Torvalds's avatar
Linus Torvalds committed
432 433
	}

Andy Grover's avatar
Andy Grover committed
434 435
	switch (register_id) {
	case ACPI_REGISTER_PM1_STATUS:           /* 16-bit access */
Linus Torvalds's avatar
Linus Torvalds committed
436 437 438 439 440 441

		value =  acpi_hw_low_level_read (16, &acpi_gbl_FADT->Xpm1a_evt_blk, 0);
		value |= acpi_hw_low_level_read (16, &acpi_gbl_FADT->Xpm1b_evt_blk, 0);
		break;


Andy Grover's avatar
Andy Grover committed
442
	case ACPI_REGISTER_PM1_ENABLE:           /* 16-bit access*/
Linus Torvalds's avatar
Linus Torvalds committed
443

Andy Grover's avatar
Andy Grover committed
444
		bank_offset = ACPI_DIV_2 (acpi_gbl_FADT->pm1_evt_len);
Linus Torvalds's avatar
Linus Torvalds committed
445 446 447 448 449
		value =  acpi_hw_low_level_read (16, &acpi_gbl_FADT->Xpm1a_evt_blk, bank_offset);
		value |= acpi_hw_low_level_read (16, &acpi_gbl_FADT->Xpm1b_evt_blk, bank_offset);
		break;


Andy Grover's avatar
Andy Grover committed
450
	case ACPI_REGISTER_PM1_CONTROL:          /* 16-bit access */
Linus Torvalds's avatar
Linus Torvalds committed
451

Linus Torvalds's avatar
Linus Torvalds committed
452 453
		value =  acpi_hw_low_level_read (16, &acpi_gbl_FADT->Xpm1a_cnt_blk, 0);
		value |= acpi_hw_low_level_read (16, &acpi_gbl_FADT->Xpm1b_cnt_blk, 0);
Linus Torvalds's avatar
Linus Torvalds committed
454 455 456
		break;


Andy Grover's avatar
Andy Grover committed
457
	case ACPI_REGISTER_PM2_CONTROL:          /* 8-bit access */
Linus Torvalds's avatar
Linus Torvalds committed
458 459 460 461 462

		value =  acpi_hw_low_level_read (8, &acpi_gbl_FADT->Xpm2_cnt_blk, 0);
		break;


Andy Grover's avatar
Andy Grover committed
463
	case ACPI_REGISTER_PM_TIMER:             /* 32-bit access */
Linus Torvalds's avatar
Linus Torvalds committed
464 465 466 467

		value =  acpi_hw_low_level_read (32, &acpi_gbl_FADT->Xpm_tmr_blk, 0);
		break;

Andy Grover's avatar
Andy Grover committed
468
	case ACPI_REGISTER_SMI_COMMAND_BLOCK:    /* 8-bit access */
Linus Torvalds's avatar
Linus Torvalds committed
469

Linus Torvalds's avatar
Linus Torvalds committed
470
		acpi_os_read_port (acpi_gbl_FADT->smi_cmd, &value, 8);
Linus Torvalds's avatar
Linus Torvalds committed
471 472 473
		break;

	default:
Linus Torvalds's avatar
Linus Torvalds committed
474
		/* Value will be returned as 0 */
Linus Torvalds's avatar
Linus Torvalds committed
475 476 477 478
		break;
	}

	if (ACPI_MTX_LOCK == use_lock) {
Andy Grover's avatar
Andy Grover committed
479
		(void) acpi_ut_release_mutex (ACPI_MTX_HARDWARE);
Linus Torvalds's avatar
Linus Torvalds committed
480 481
	}

Linus Torvalds's avatar
Linus Torvalds committed
482
	return_VALUE (value);
Linus Torvalds's avatar
Linus Torvalds committed
483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508
}


/******************************************************************************
 *
 * FUNCTION:    Acpi_hw_register_write
 *
 * PARAMETERS:  Use_lock               - Mutex hw access.
 *              Register_id            - Register_iD + Offset.
 *
 * RETURN:      Value read or written.
 *
 * DESCRIPTION: Acpi register Write function.  Registers are written at the
 *              given offset.
 *
 ******************************************************************************/

void
acpi_hw_register_write (
	u8                      use_lock,
	u32                     register_id,
	u32                     value)
{
	u32                     bank_offset;


Andy Grover's avatar
Andy Grover committed
509
	ACPI_FUNCTION_TRACE ("Hw_register_write");
Linus Torvalds's avatar
Linus Torvalds committed
510 511


Linus Torvalds's avatar
Linus Torvalds committed
512
	if (ACPI_MTX_LOCK == use_lock) {
Andy Grover's avatar
Andy Grover committed
513 514 515
		if (ACPI_FAILURE (acpi_ut_acquire_mutex (ACPI_MTX_HARDWARE))) {
			return_VOID;
		}
Linus Torvalds's avatar
Linus Torvalds committed
516 517
	}

Andy Grover's avatar
Andy Grover committed
518 519
	switch (register_id) {
	case ACPI_REGISTER_PM1_STATUS:           /* 16-bit access */
Linus Torvalds's avatar
Linus Torvalds committed
520 521 522 523 524 525

		acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->Xpm1a_evt_blk, 0);
		acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->Xpm1b_evt_blk, 0);
		break;


Andy Grover's avatar
Andy Grover committed
526
	case ACPI_REGISTER_PM1_ENABLE:           /* 16-bit access*/
Linus Torvalds's avatar
Linus Torvalds committed
527

Andy Grover's avatar
Andy Grover committed
528
		bank_offset = ACPI_DIV_2 (acpi_gbl_FADT->pm1_evt_len);
Linus Torvalds's avatar
Linus Torvalds committed
529 530 531 532 533
		acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->Xpm1a_evt_blk, bank_offset);
		acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->Xpm1b_evt_blk, bank_offset);
		break;


Andy Grover's avatar
Andy Grover committed
534
	case ACPI_REGISTER_PM1_CONTROL:          /* 16-bit access */
Linus Torvalds's avatar
Linus Torvalds committed
535

Linus Torvalds's avatar
Linus Torvalds committed
536 537 538
		acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->Xpm1a_cnt_blk, 0);
		acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->Xpm1b_cnt_blk, 0);
		break;
Linus Torvalds's avatar
Linus Torvalds committed
539 540


Andy Grover's avatar
Andy Grover committed
541
	case ACPI_REGISTER_PM1A_CONTROL:         /* 16-bit access */
Linus Torvalds's avatar
Linus Torvalds committed
542 543 544 545 546

		acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->Xpm1a_cnt_blk, 0);
		break;


Andy Grover's avatar
Andy Grover committed
547
	case ACPI_REGISTER_PM1B_CONTROL:         /* 16-bit access */
Linus Torvalds's avatar
Linus Torvalds committed
548

Linus Torvalds's avatar
Linus Torvalds committed
549
		acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->Xpm1b_cnt_blk, 0);
Linus Torvalds's avatar
Linus Torvalds committed
550 551 552
		break;


Andy Grover's avatar
Andy Grover committed
553
	case ACPI_REGISTER_PM2_CONTROL:          /* 8-bit access */
Linus Torvalds's avatar
Linus Torvalds committed
554 555 556 557 558

		acpi_hw_low_level_write (8, value, &acpi_gbl_FADT->Xpm2_cnt_blk, 0);
		break;


Andy Grover's avatar
Andy Grover committed
559
	case ACPI_REGISTER_PM_TIMER:             /* 32-bit access */
Linus Torvalds's avatar
Linus Torvalds committed
560 561 562 563 564

		acpi_hw_low_level_write (32, value, &acpi_gbl_FADT->Xpm_tmr_blk, 0);
		break;


Andy Grover's avatar
Andy Grover committed
565
	case ACPI_REGISTER_SMI_COMMAND_BLOCK:    /* 8-bit access */
Linus Torvalds's avatar
Linus Torvalds committed
566

Andy Grover's avatar
Andy Grover committed
567
		/* SMI_CMD is currently always in IO space */
Linus Torvalds's avatar
Linus Torvalds committed
568

Linus Torvalds's avatar
Linus Torvalds committed
569
		acpi_os_write_port (acpi_gbl_FADT->smi_cmd, value, 8);
Linus Torvalds's avatar
Linus Torvalds committed
570 571 572 573 574 575 576 577 578
		break;


	default:
		value = 0;
		break;
	}

	if (ACPI_MTX_LOCK == use_lock) {
Andy Grover's avatar
Andy Grover committed
579
		(void) acpi_ut_release_mutex (ACPI_MTX_HARDWARE);
Linus Torvalds's avatar
Linus Torvalds committed
580 581
	}

Linus Torvalds's avatar
Linus Torvalds committed
582
	return_VOID;
Linus Torvalds's avatar
Linus Torvalds committed
583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602
}


/******************************************************************************
 *
 * FUNCTION:    Acpi_hw_low_level_read
 *
 * PARAMETERS:  Register            - GAS register structure
 *              Offset              - Offset from the base address in the GAS
 *              Width               - 8, 16, or 32
 *
 * RETURN:      Value read
 *
 * DESCRIPTION: Read from either memory, IO, or PCI config space.
 *
 ******************************************************************************/

u32
acpi_hw_low_level_read (
	u32                     width,
Linus Torvalds's avatar
Linus Torvalds committed
603
	acpi_generic_address    *reg,
Linus Torvalds's avatar
Linus Torvalds committed
604 605 606 607 608
	u32                     offset)
{
	u32                     value = 0;
	ACPI_PHYSICAL_ADDRESS   mem_address;
	ACPI_IO_ADDRESS         io_address;
Linus Torvalds's avatar
Linus Torvalds committed
609 610 611 612
	acpi_pci_id             pci_id;
	u16                     pci_register;


Andy Grover's avatar
Andy Grover committed
613
	ACPI_FUNCTION_ENTRY ();
Linus Torvalds's avatar
Linus Torvalds committed
614 615 616 617 618 619 620


	/*
	 * Must have a valid pointer to a GAS structure, and
	 * a non-zero address within
	 */
	if ((!reg) ||
Linus Torvalds's avatar
Linus Torvalds committed
621
		(!ACPI_VALID_ADDRESS (reg->address))) {
Linus Torvalds's avatar
Linus Torvalds committed
622 623 624 625 626 627 628
		return 0;
	}

	/*
	 * Three address spaces supported:
	 * Memory, Io, or PCI config.
	 */
Linus Torvalds's avatar
Linus Torvalds committed
629 630
	switch (reg->address_space_id) {
	case ACPI_ADR_SPACE_SYSTEM_MEMORY:
Linus Torvalds's avatar
Linus Torvalds committed
631 632 633

		mem_address = (ACPI_PHYSICAL_ADDRESS) (ACPI_GET_ADDRESS (reg->address) + offset);

Linus Torvalds's avatar
Linus Torvalds committed
634
		acpi_os_read_memory (mem_address, &value, width);
Linus Torvalds's avatar
Linus Torvalds committed
635 636 637
		break;


Linus Torvalds's avatar
Linus Torvalds committed
638
	case ACPI_ADR_SPACE_SYSTEM_IO:
Linus Torvalds's avatar
Linus Torvalds committed
639 640 641

		io_address = (ACPI_IO_ADDRESS) (ACPI_GET_ADDRESS (reg->address) + offset);

Linus Torvalds's avatar
Linus Torvalds committed
642
		acpi_os_read_port (io_address, &value, width);
Linus Torvalds's avatar
Linus Torvalds committed
643 644 645
		break;


Linus Torvalds's avatar
Linus Torvalds committed
646
	case ACPI_ADR_SPACE_PCI_CONFIG:
Linus Torvalds's avatar
Linus Torvalds committed
647

Linus Torvalds's avatar
Linus Torvalds committed
648 649 650 651 652
		pci_id.segment = 0;
		pci_id.bus     = 0;
		pci_id.device  = ACPI_PCI_DEVICE (ACPI_GET_ADDRESS (reg->address));
		pci_id.function = ACPI_PCI_FUNCTION (ACPI_GET_ADDRESS (reg->address));
		pci_register   = (u16) (ACPI_PCI_REGISTER (ACPI_GET_ADDRESS (reg->address)) + offset);
Linus Torvalds's avatar
Linus Torvalds committed
653

Linus Torvalds's avatar
Linus Torvalds committed
654
		acpi_os_read_pci_configuration (&pci_id, pci_register, &value, width);
Linus Torvalds's avatar
Linus Torvalds committed
655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681
		break;
	}

	return value;
}


/******************************************************************************
 *
 * FUNCTION:    Acpi_hw_low_level_write
 *
 * PARAMETERS:  Width               - 8, 16, or 32
 *              Value               - To be written
 *              Register            - GAS register structure
 *              Offset              - Offset from the base address in the GAS
 *
 *
 * RETURN:      Value read
 *
 * DESCRIPTION: Read from either memory, IO, or PCI config space.
 *
 ******************************************************************************/

void
acpi_hw_low_level_write (
	u32                     width,
	u32                     value,
Linus Torvalds's avatar
Linus Torvalds committed
682
	acpi_generic_address    *reg,
Linus Torvalds's avatar
Linus Torvalds committed
683 684 685 686
	u32                     offset)
{
	ACPI_PHYSICAL_ADDRESS   mem_address;
	ACPI_IO_ADDRESS         io_address;
Linus Torvalds's avatar
Linus Torvalds committed
687 688 689 690
	acpi_pci_id             pci_id;
	u16                     pci_register;


Andy Grover's avatar
Andy Grover committed
691
	ACPI_FUNCTION_ENTRY ();
Linus Torvalds's avatar
Linus Torvalds committed
692 693 694 695 696 697 698


	/*
	 * Must have a valid pointer to a GAS structure, and
	 * a non-zero address within
	 */
	if ((!reg) ||
Linus Torvalds's avatar
Linus Torvalds committed
699
		(!ACPI_VALID_ADDRESS (reg->address))) {
Linus Torvalds's avatar
Linus Torvalds committed
700 701 702 703 704 705 706
		return;
	}

	/*
	 * Three address spaces supported:
	 * Memory, Io, or PCI config.
	 */
Linus Torvalds's avatar
Linus Torvalds committed
707 708
	switch (reg->address_space_id) {
	case ACPI_ADR_SPACE_SYSTEM_MEMORY:
Linus Torvalds's avatar
Linus Torvalds committed
709 710 711

		mem_address = (ACPI_PHYSICAL_ADDRESS) (ACPI_GET_ADDRESS (reg->address) + offset);

Linus Torvalds's avatar
Linus Torvalds committed
712
		acpi_os_write_memory (mem_address, value, width);
Linus Torvalds's avatar
Linus Torvalds committed
713 714 715
		break;


Linus Torvalds's avatar
Linus Torvalds committed
716
	case ACPI_ADR_SPACE_SYSTEM_IO:
Linus Torvalds's avatar
Linus Torvalds committed
717 718 719

		io_address = (ACPI_IO_ADDRESS) (ACPI_GET_ADDRESS (reg->address) + offset);

Linus Torvalds's avatar
Linus Torvalds committed
720
		acpi_os_write_port (io_address, value, width);
Linus Torvalds's avatar
Linus Torvalds committed
721 722 723
		break;


Linus Torvalds's avatar
Linus Torvalds committed
724
	case ACPI_ADR_SPACE_PCI_CONFIG:
Linus Torvalds's avatar
Linus Torvalds committed
725

Linus Torvalds's avatar
Linus Torvalds committed
726 727 728 729 730
		pci_id.segment = 0;
		pci_id.bus     = 0;
		pci_id.device  = ACPI_PCI_DEVICE (ACPI_GET_ADDRESS (reg->address));
		pci_id.function = ACPI_PCI_FUNCTION (ACPI_GET_ADDRESS (reg->address));
		pci_register   = (u16) (ACPI_PCI_REGISTER (ACPI_GET_ADDRESS (reg->address)) + offset);
Linus Torvalds's avatar
Linus Torvalds committed
731

Linus Torvalds's avatar
Linus Torvalds committed
732
		acpi_os_write_pci_configuration (&pci_id, pci_register, value, width);
Linus Torvalds's avatar
Linus Torvalds committed
733 734 735
		break;
	}
}