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); }
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); }
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); }
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); }
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); }
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); }
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; } }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }