Пример #1
0
static int
acpi_ec_write (
	struct acpi_ec		*ec,
	u8			address,
	u8			data)
{
	int			result = 0;
	acpi_status		status = AE_OK;
	unsigned long		flags = 0;
	u32			glk = 0;

	ACPI_FUNCTION_TRACE("acpi_ec_write");

	if (!ec)
		return_VALUE(-EINVAL);

	if (ec->global_lock) {
		status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk);
		if (ACPI_FAILURE(status))
			return_VALUE(-ENODEV);
	}

	spin_lock_irqsave(&ec->lock, flags);

	acpi_hw_low_level_write(8, ACPI_EC_COMMAND_WRITE, &ec->command_addr);
	result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE);
	if (result)
		goto end;

	acpi_hw_low_level_write(8, address, &ec->data_addr);
	result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE);
	if (result)
		goto end;

	acpi_hw_low_level_write(8, data, &ec->data_addr);
	result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE);
	if (result)
		goto end;

	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Wrote [%02x] to address [%02x]\n",
		data, address));

end:
	spin_unlock_irqrestore(&ec->lock, flags);

	if (ec->global_lock)
		acpi_release_global_lock(glk);

	return_VALUE(result);
}
Пример #2
0
acpi_status
acpi_hw_enable_gpe (
	struct acpi_gpe_event_info      *gpe_event_info)
{
	u32                             in_byte;
	acpi_status                     status;


	ACPI_FUNCTION_ENTRY ();


	/*
	 * Read the current value of the register, set the appropriate bit
	 * to enable the GPE, and write out the new register.
	 */
	status = acpi_hw_low_level_read (8, &in_byte,
			  &gpe_event_info->register_info->enable_address);
	if (ACPI_FAILURE (status)) {
		return (status);
	}

	/* Write with the new GPE bit enabled */

	status = acpi_hw_low_level_write (8, (in_byte | gpe_event_info->bit_mask),
			  &gpe_event_info->register_info->enable_address);

	return (status);
}
Пример #3
0
static acpi_status
acpi_hw_enable_non_wakeup_gpe_block (
	struct acpi_gpe_xrupt_info      *gpe_xrupt_info,
	struct acpi_gpe_block_info      *gpe_block)
{
	u32                             i;
	struct acpi_gpe_register_info   *gpe_register_info;
	acpi_status                     status;


	/* This callback processes one entire GPE block */

	/* Get the register info for the entire GPE block */

	gpe_register_info = gpe_block->register_info;

	/* Examine each GPE register within the block */

	for (i = 0; i < gpe_block->register_count; i++) {
		/*
		 * We previously stored the enabled status of all GPEs.
		 * Blast them back in.
		 */
		status = acpi_hw_low_level_write (8, gpe_register_info->enable,
				 &gpe_register_info->enable_address);
		if (ACPI_FAILURE (status)) {
			return (status);
		}

		gpe_register_info++;
	}


	return (AE_OK);
}
Пример #4
0
acpi_status
acpi_hw_enable_runtime_gpe_block(struct acpi_gpe_xrupt_info * gpe_xrupt_info,
				 struct acpi_gpe_block_info * gpe_block)
{
	u32 i;
	acpi_status status;

	/* NOTE: assumes that all GPEs are currently disabled */

	/* Examine each GPE Register within the block */

	for (i = 0; i < gpe_block->register_count; i++) {
		if (!gpe_block->register_info[i].enable_for_run) {
			continue;
		}

		/* Enable all "runtime" GPEs in this register */

		status =
		    acpi_hw_low_level_write(8,
					    gpe_block->register_info[i].
					    enable_for_run,
					    &gpe_block->register_info[i].
					    enable_address);
		if (ACPI_FAILURE(status)) {
			return (status);
		}
	}

	return (AE_OK);
}
Пример #5
0
acpi_status
acpi_hw_clear_gpe_block (
	struct acpi_gpe_xrupt_info      *gpe_xrupt_info,
	struct acpi_gpe_block_info      *gpe_block)
{
	u32                             i;
	struct acpi_gpe_register_info   *gpe_register_info;
	acpi_status                     status;


	/* Get the register info for the entire GPE block */

	gpe_register_info = gpe_block->register_info;

	/* Examine each GPE Register within the block */

	for (i = 0; i < gpe_block->register_count; i++) {
		status = acpi_hw_low_level_write (8, 0xFF,
				 &gpe_block->register_info[i].status_address);
		if (ACPI_FAILURE (status)) {
			return (status);
		}
	}

	return (AE_OK);
}
Пример #6
0
static acpi_status
acpi_hw_enable_wakeup_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
				struct acpi_gpe_block_info *gpe_block)
{
	u32 i;
	acpi_status status;

	/* Examine each GPE Register within the block */

	for (i = 0; i < gpe_block->register_count; i++) {
		if (!gpe_block->register_info[i].enable_for_wake) {
			continue;
		}

		/* Enable all "wake" GPEs in this register */

		status = acpi_hw_low_level_write(8,
						 gpe_block->register_info[i].
						 enable_for_wake,
						 &gpe_block->register_info[i].
						 enable_address);
		if (ACPI_FAILURE(status)) {
			return (status);
		}
	}

	return (AE_OK);
}
Пример #7
0
void acpi_reboot(void)
{
	struct acpi_generic_address *rr;
	u8 reset_value;

	rr = &acpi_gbl_FADT.reset_register;

	/* Is the reset register supported? The spec says we should be
	 * checking the bit width and bit offset, but Windows ignores
	 * these fields */
	if (!(acpi_gbl_FADT.flags & ACPI_FADT_RESET_REGISTER))
		return;

	reset_value = acpi_gbl_FADT.reset_value;

	/* The reset register can only exist in I/O, Memory or PCI config space
	 * on a device on bus 0. */
	switch (rr->space_id) {
	case ACPI_ADR_SPACE_PCI_CONFIG:
		printk("Resetting with ACPI PCI RESET_REG.\n");
		/* Write the value that resets us. */
		pci_conf_write8(0, 0,
				(rr->address >> 32) & 31,
				(rr->address >> 16) & 7,
				(rr->address & 255),
				reset_value);
		break;
	case ACPI_ADR_SPACE_SYSTEM_MEMORY:
	case ACPI_ADR_SPACE_SYSTEM_IO:
		printk("Resetting with ACPI MEMORY or I/O RESET_REG.\n");
		acpi_hw_low_level_write(8, reset_value, rr);
		break;
	}
}
Пример #8
0
void acpi_reboot(void)
{
	struct acpi_generic_address *rr;
	struct pci_bus *bus0;
	u8 reset_value;
	unsigned int devfn;

	if (acpi_disabled)
		return;

	rr = &acpi_gbl_FADT.reset_register;

	/*
	 * For those systems that have not been whitelisted, check the ACPI
	 * flags and the register layout.
	 */
	if (!dmi_check_system(reboot_dmi_whitelist)) {
		/* Is the reset register supported? */
		if (!(acpi_gbl_FADT.flags & ACPI_FADT_RESET_REGISTER))
			return;
		/* Is the width and ofset as specified? */
		if (rr->bit_width != 8 || rr->bit_offset != 0)
			return;
	}

	reset_value = acpi_gbl_FADT.reset_value;

	/* The reset register can only exist in I/O, Memory or PCI config space
	 * on a device on bus 0. */
	switch (rr->space_id) {
	case ACPI_ADR_SPACE_PCI_CONFIG:
		/* The reset register can only live on bus 0. */
		bus0 = pci_find_bus(0, 0);
		if (!bus0)
			return;
		/* Form PCI device/function pair. */
		devfn = PCI_DEVFN((rr->address >> 32) & 0xffff,
				  (rr->address >> 16) & 0xffff);
		printk(KERN_DEBUG "Resetting with ACPI PCI RESET_REG.");
		/* Write the value that resets us. */
		pci_bus_write_config_byte(bus0, devfn,
				(rr->address & 0xffff), reset_value);
		break;

	case ACPI_ADR_SPACE_SYSTEM_MEMORY:
	case ACPI_ADR_SPACE_SYSTEM_IO:
		printk(KERN_DEBUG "ACPI MEMORY or I/O RESET_REG.\n");
		acpi_hw_low_level_write(8, reset_value, rr);
		break;
	}
	/* Wait ten seconds */
	acpi_os_stall(10000000);
}
Пример #9
0
static int
acpi_ec_query (
	struct acpi_ec		*ec,
	u32			*data)
{
	int			result = 0;
	acpi_status		status = AE_OK;
	unsigned long		flags = 0;
	u32			glk = 0;

	ACPI_FUNCTION_TRACE("acpi_ec_query");

	if (!ec || !data)
		return_VALUE(-EINVAL);

	*data = 0;

	if (ec->global_lock) {
		status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk);
		if (ACPI_FAILURE(status))
			return_VALUE(-ENODEV);
	}

	/*
	 * Query the EC to find out which _Qxx method we need to evaluate.
	 * Note that successful completion of the query causes the ACPI_EC_SCI
	 * bit to be cleared (and thus clearing the interrupt source).
	 */
	spin_lock_irqsave(&ec->lock, flags);

	acpi_hw_low_level_write(8, ACPI_EC_COMMAND_QUERY, &ec->command_addr);
	result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF);
	if (result)
		goto end;
	
	acpi_hw_low_level_read(8, data, &ec->data_addr);
	if (!*data)
		result = -ENODATA;

end:
	spin_unlock_irqrestore(&ec->lock, flags);

	if (ec->global_lock)
		acpi_release_global_lock(glk);

	return_VALUE(result);
}
Пример #10
0
static acpi_status
acpi_hw_disable_non_wakeup_gpe_block (
	struct acpi_gpe_xrupt_info      *gpe_xrupt_info,
	struct acpi_gpe_block_info      *gpe_block)
{
	u32                             i;
	struct acpi_gpe_register_info   *gpe_register_info;
	u32                             in_value;
	acpi_status                     status;


	/* Get the register info for the entire GPE block */

	gpe_register_info = gpe_block->register_info;

	/* Examine each GPE Register within the block */

	for (i = 0; i < gpe_block->register_count; i++) {
		/*
		 * Read the enabled status of all GPEs. We
		 * will be using it to restore all the GPEs later.
		 */
		status = acpi_hw_low_level_read (8, &in_value,
				 &gpe_register_info->enable_address);
		if (ACPI_FAILURE (status)) {
			return (status);
		}

		gpe_register_info->enable = (u8) in_value;

		/*
		 * Disable all GPEs except wakeup GPEs.
		 */
		status = acpi_hw_low_level_write (8, gpe_register_info->wake_enable,
				&gpe_register_info->enable_address);
		if (ACPI_FAILURE (status)) {
			return (status);
		}

		gpe_register_info++;
	}

	return (AE_OK);
}
Пример #11
0
acpi_status
acpi_hw_clear_gpe (
	struct acpi_gpe_event_info      *gpe_event_info)
{
	acpi_status                     status;


	ACPI_FUNCTION_ENTRY ();


	/*
	 * Write a one to the appropriate bit in the status register to
	 * clear this GPE.
	 */
	status = acpi_hw_low_level_write (8, gpe_event_info->bit_mask,
			  &gpe_event_info->register_info->status_address);

	return (status);
}
Пример #12
0
acpi_status
acpi_hw_disable_gpe (
	struct acpi_gpe_event_info      *gpe_event_info)
{
	u32                             in_byte;
	acpi_status                     status;
	struct acpi_gpe_register_info   *gpe_register_info;


	ACPI_FUNCTION_ENTRY ();


	/* Get the info block for the entire GPE register */

	gpe_register_info = gpe_event_info->register_info;
	if (!gpe_register_info) {
		return (AE_BAD_PARAMETER);
	}

	/*
	 * Read the current value of the register, clear the appropriate bit,
	 * and write out the new register value to disable the GPE.
	 */
	status = acpi_hw_low_level_read (8, &in_byte,
			  &gpe_register_info->enable_address);
	if (ACPI_FAILURE (status)) {
		return (status);
	}

	/* Write the byte with this GPE bit cleared */

	status = acpi_hw_low_level_write (8, (in_byte & ~(gpe_event_info->bit_mask)),
			  &gpe_register_info->enable_address);
	if (ACPI_FAILURE (status)) {
		return (status);
	}

	acpi_hw_disable_gpe_for_wakeup (gpe_event_info);
	return (AE_OK);
}
Пример #13
0
acpi_status
acpi_hw_write_gpe_enable_reg(struct acpi_gpe_event_info *gpe_event_info)
{
	struct acpi_gpe_register_info *gpe_register_info;
	acpi_status status;

	ACPI_FUNCTION_ENTRY();

	/* Get the info block for the entire GPE register */

	gpe_register_info = gpe_event_info->register_info;
	if (!gpe_register_info) {
		return (AE_NOT_EXIST);
	}

	/* Write the entire GPE (runtime) enable register */

	status = acpi_hw_low_level_write(8, gpe_register_info->enable_for_run,
					 &gpe_register_info->enable_address);

	return (status);
}
Пример #14
0
acpi_status acpi_hw_clear_gpe(struct acpi_gpe_event_info * gpe_event_info)
{
	acpi_status status;
	u8 register_bit;

	ACPI_FUNCTION_ENTRY();

	register_bit = (u8)
	    (1 <<
	     (gpe_event_info->gpe_number -
	      gpe_event_info->register_info->base_gpe_number));

	/*
	 * Write a one to the appropriate bit in the status register to
	 * clear this GPE.
	 */
	status = acpi_hw_low_level_write(8, register_bit,
					 &gpe_event_info->register_info->
					 status_address);

	return (status);
}
Пример #15
0
acpi_status
acpi_hw_clear_gpe_block(struct acpi_gpe_xrupt_info * gpe_xrupt_info,
			struct acpi_gpe_block_info * gpe_block)
{
	u32 i;
	acpi_status status;

	/* Examine each GPE Register within the block */

	for (i = 0; i < gpe_block->register_count; i++) {

		/* Clear status on all GPEs in this register */

		status = acpi_hw_low_level_write(8, 0xFF,
						 &gpe_block->register_info[i].
						 status_address);
		if (ACPI_FAILURE(status)) {
			return (status);
		}
	}

	return (AE_OK);
}
Пример #16
0
static acpi_status
acpi_ev_create_gpe_info_blocks(struct acpi_gpe_block_info *gpe_block)
{
    struct acpi_gpe_register_info *gpe_register_info = NULL;
    struct acpi_gpe_event_info *gpe_event_info = NULL;
    struct acpi_gpe_event_info *this_event;
    struct acpi_gpe_register_info *this_register;
    acpi_native_uint i;
    acpi_native_uint j;
    acpi_status status;

    ACPI_FUNCTION_TRACE(ev_create_gpe_info_blocks);

    /* Allocate the GPE register information block */

    gpe_register_info = ACPI_ALLOCATE_ZEROED((acpi_size) gpe_block->
                         register_count *
                         sizeof(struct
                            acpi_gpe_register_info));
    if (!gpe_register_info) {
        ACPI_ERROR((AE_INFO,
                "Could not allocate the GpeRegisterInfo table"));
        return_ACPI_STATUS(AE_NO_MEMORY);
    }

    /*
     * Allocate the GPE event_info block. There are eight distinct GPEs
     * per register. Initialization to zeros is sufficient.
     */
    gpe_event_info = ACPI_ALLOCATE_ZEROED(((acpi_size) gpe_block->
                           register_count *
                           ACPI_GPE_REGISTER_WIDTH) *
                          sizeof(struct
                             acpi_gpe_event_info));
    if (!gpe_event_info) {
        ACPI_ERROR((AE_INFO,
                "Could not allocate the GpeEventInfo table"));
        status = AE_NO_MEMORY;
        goto error_exit;
    }

    /* Save the new Info arrays in the GPE block */

    gpe_block->register_info = gpe_register_info;
    gpe_block->event_info = gpe_event_info;

    /*
     * Initialize the GPE Register and Event structures. A goal of these
     * tables is to hide the fact that there are two separate GPE register sets
     * in a given GPE hardware block, the status registers occupy the first half,
     * and the enable registers occupy the second half.
     */
    this_register = gpe_register_info;
    this_event = gpe_event_info;

    for (i = 0; i < gpe_block->register_count; i++) {

        /* Init the register_info for this GPE register (8 GPEs) */

        this_register->base_gpe_number =
            (u8) (gpe_block->block_base_number +
              (i * ACPI_GPE_REGISTER_WIDTH));

        this_register->status_address.address =
            gpe_block->block_address.address + i;

        this_register->enable_address.address =
            gpe_block->block_address.address + i +
            gpe_block->register_count;

        this_register->status_address.space_id =
            gpe_block->block_address.space_id;
        this_register->enable_address.space_id =
            gpe_block->block_address.space_id;
        this_register->status_address.bit_width =
            ACPI_GPE_REGISTER_WIDTH;
        this_register->enable_address.bit_width =
            ACPI_GPE_REGISTER_WIDTH;
        this_register->status_address.bit_offset =
            ACPI_GPE_REGISTER_WIDTH;
        this_register->enable_address.bit_offset =
            ACPI_GPE_REGISTER_WIDTH;

        /* Init the event_info for each GPE within this register */

        for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++) {
            this_event->gpe_number =
                (u8) (this_register->base_gpe_number + j);
            this_event->register_info = this_register;
            this_event++;
        }

        /* Disable all GPEs within this register */

        status = acpi_hw_low_level_write(ACPI_GPE_REGISTER_WIDTH, 0x00,
                         &this_register->
                         enable_address);
        if (ACPI_FAILURE(status)) {
            goto error_exit;
        }

        /* Clear any pending GPE events within this register */

        status = acpi_hw_low_level_write(ACPI_GPE_REGISTER_WIDTH, 0xFF,
                         &this_register->
                         status_address);
        if (ACPI_FAILURE(status)) {
            goto error_exit;
        }

        this_register++;
    }

    return_ACPI_STATUS(AE_OK);

      error_exit:
    if (gpe_register_info) {
        ACPI_FREE(gpe_register_info);
    }
    if (gpe_event_info) {
        ACPI_FREE(gpe_event_info);
    }

    return_ACPI_STATUS(status);
}
Пример #17
0
static acpi_status
acpi_ev_create_gpe_info_blocks (
	struct acpi_gpe_block_info      *gpe_block)
{
	struct acpi_gpe_register_info   *gpe_register_info = NULL;
	struct acpi_gpe_event_info      *gpe_event_info = NULL;
	struct acpi_gpe_event_info      *this_event;
	struct acpi_gpe_register_info   *this_register;
	acpi_native_uint                i;
	acpi_native_uint                j;
	acpi_status                     status;


	ACPI_FUNCTION_TRACE ("ev_create_gpe_info_blocks");


	/* Allocate the GPE register information block */

	gpe_register_info = ACPI_MEM_CALLOCATE (
			  (acpi_size) gpe_block->register_count *
			  sizeof (struct acpi_gpe_register_info));
	if (!gpe_register_info) {
		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
			"Could not allocate the gpe_register_info table\n"));
		return_ACPI_STATUS (AE_NO_MEMORY);
	}

	/*
	 * Allocate the GPE event_info block. There are eight distinct GPEs
	 * per register.  Initialization to zeros is sufficient.
	 */
	gpe_event_info = ACPI_MEM_CALLOCATE (
			   ((acpi_size) gpe_block->register_count * ACPI_GPE_REGISTER_WIDTH) *
			   sizeof (struct acpi_gpe_event_info));
	if (!gpe_event_info) {
		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Could not allocate the gpe_event_info table\n"));
		status = AE_NO_MEMORY;
		goto error_exit;
	}

	/* Save the new Info arrays in the GPE block */

	gpe_block->register_info = gpe_register_info;
	gpe_block->event_info  = gpe_event_info;

	/*
	 * Initialize the GPE Register and Event structures.  A goal of these
	 * tables is to hide the fact that there are two separate GPE register sets
	 * in a given gpe hardware block, the status registers occupy the first half,
	 * and the enable registers occupy the second half.
	 */
	this_register = gpe_register_info;
	this_event   = gpe_event_info;

	for (i = 0; i < gpe_block->register_count; i++) {
		/* Init the register_info for this GPE register (8 GPEs) */

		this_register->base_gpe_number = (u8) (gpe_block->block_base_number +
				   (i * ACPI_GPE_REGISTER_WIDTH));

		ACPI_STORE_ADDRESS (this_register->status_address.address,
				 (gpe_block->block_address.address
				 + i));

		ACPI_STORE_ADDRESS (this_register->enable_address.address,
				 (gpe_block->block_address.address
				 + i
				 + gpe_block->register_count));

		this_register->status_address.address_space_id = gpe_block->block_address.address_space_id;
		this_register->enable_address.address_space_id = gpe_block->block_address.address_space_id;
		this_register->status_address.register_bit_width = ACPI_GPE_REGISTER_WIDTH;
		this_register->enable_address.register_bit_width = ACPI_GPE_REGISTER_WIDTH;
		this_register->status_address.register_bit_offset = ACPI_GPE_REGISTER_WIDTH;
		this_register->enable_address.register_bit_offset = ACPI_GPE_REGISTER_WIDTH;

		/* Init the event_info for each GPE within this register */

		for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++) {
			this_event->bit_mask = acpi_gbl_decode_to8bit[j];
			this_event->register_info = this_register;
			this_event++;
		}

		/*
		 * Clear the status/enable registers.  Note that status registers
		 * are cleared by writing a '1', while enable registers are cleared
		 * by writing a '0'.
		 */
		status = acpi_hw_low_level_write (ACPI_GPE_REGISTER_WIDTH, 0x00,
				 &this_register->enable_address);
		if (ACPI_FAILURE (status)) {
			goto error_exit;
		}

		status = acpi_hw_low_level_write (ACPI_GPE_REGISTER_WIDTH, 0xFF,
				 &this_register->status_address);
		if (ACPI_FAILURE (status)) {
			goto error_exit;
		}

		this_register++;
	}

	return_ACPI_STATUS (AE_OK);


error_exit:
	if (gpe_register_info) {
		ACPI_MEM_FREE (gpe_register_info);
	}
	if (gpe_event_info) {
		ACPI_MEM_FREE (gpe_event_info);
	}

	return_ACPI_STATUS (status);
}