Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit cd8c93a4 authored by Alexey Starikovskiy's avatar Alexey Starikovskiy Committed by Len Brown
Browse files

ACPI: EC: If ECDT is not found, look up EC in DSDT.

Some ASUS laptops access EC space from device _INI methods, but do not
provide ECDT for early EC setup. In order to make them function properly,
there is a need to find EC is DSDT before any _INI is called.

Similar functionality was turned on by acpi_fake_ecdt=1 command line
before. Now it is on all the time.

http://bugzilla.kernel.org/show_bug.cgi?id=8598



Signed-off-by: default avatarAlexey Starikovskiy <astarikovskiy@suse.de>
Signed-off-by: default avatarLen Brown <len.brown@intel.com>
parent f1cd1fe6
Loading
Loading
Loading
Loading
+28 −22
Original line number Original line Diff line number Diff line
@@ -664,30 +664,32 @@ acpi_ec_register_query_methods(acpi_handle handle, u32 level,
	return AE_OK;
	return AE_OK;
}
}


static int ec_parse_device(struct acpi_ec *ec, acpi_handle handle)
static acpi_status
ec_parse_device(acpi_handle handle, u32 Level, void *context, void **retval)
{
{
	if (ACPI_FAILURE(acpi_walk_resources(handle, METHOD_NAME__CRS,
	acpi_status status;
				     ec_parse_io_ports, ec)))

		return -EINVAL;
	struct acpi_ec *ec = context;
	status = acpi_walk_resources(handle, METHOD_NAME__CRS,
				     ec_parse_io_ports, ec);
	if (ACPI_FAILURE(status))
		return status;


	/* Get GPE bit assignment (EC events). */
	/* Get GPE bit assignment (EC events). */
	/* TODO: Add support for _GPE returning a package */
	/* TODO: Add support for _GPE returning a package */
	if (ACPI_FAILURE(acpi_evaluate_integer(handle, "_GPE", NULL, &ec->gpe)))
	status = acpi_evaluate_integer(handle, "_GPE", NULL, &ec->gpe);
		return -EINVAL;
	if (ACPI_FAILURE(status))
		return status;


	/* Use the global lock for all EC transactions? */
	/* Use the global lock for all EC transactions? */
	acpi_evaluate_integer(handle, "_GLK", NULL, &ec->global_lock);
	acpi_evaluate_integer(handle, "_GLK", NULL, &ec->global_lock);


	/* Find and register all query methods */
	acpi_walk_namespace(ACPI_TYPE_METHOD, handle, 1,
			    acpi_ec_register_query_methods, ec, NULL);

	ec->handle = handle;
	ec->handle = handle;


	printk(KERN_INFO PREFIX "GPE = 0x%lx, I/O: command/status = 0x%lx, data = 0x%lx",
	printk(KERN_INFO PREFIX "GPE = 0x%lx, I/O: command/status = 0x%lx, data = 0x%lx",
			  ec->gpe, ec->command_addr, ec->data_addr);
			  ec->gpe, ec->command_addr, ec->data_addr);


	return 0;
	return AE_CTRL_TERMINATE;
}
}


static int acpi_ec_add(struct acpi_device *device)
static int acpi_ec_add(struct acpi_device *device)
@@ -704,7 +706,8 @@ static int acpi_ec_add(struct acpi_device *device)
	if (!ec)
	if (!ec)
		return -ENOMEM;
		return -ENOMEM;


	if (ec_parse_device(ec, device->handle)) {
	if (ec_parse_device(device->handle, 0, ec, NULL) !=
	    AE_CTRL_TERMINATE) {
		kfree(ec);
		kfree(ec);
		return -EINVAL;
		return -EINVAL;
	}
	}
@@ -867,18 +870,21 @@ int __init acpi_ec_ecdt_probe(void)
	/*
	/*
	 * Generate a boot ec context
	 * Generate a boot ec context
	 */
	 */

	status = acpi_get_table(ACPI_SIG_ECDT, 1,
	status = acpi_get_table(ACPI_SIG_ECDT, 1,
				(struct acpi_table_header **)&ecdt_ptr);
				(struct acpi_table_header **)&ecdt_ptr);
	if (ACPI_FAILURE(status))
	if (ACPI_SUCCESS(status)) {
		goto error;
		printk(KERN_INFO PREFIX "EC description table is found, configuring boot EC\n\n");

	printk(KERN_INFO PREFIX "EC description table is found, configuring boot EC\n");

		boot_ec->command_addr = ecdt_ptr->control.address;
		boot_ec->command_addr = ecdt_ptr->control.address;
		boot_ec->data_addr = ecdt_ptr->data.address;
		boot_ec->data_addr = ecdt_ptr->data.address;
		boot_ec->gpe = ecdt_ptr->gpe;
		boot_ec->gpe = ecdt_ptr->gpe;
		boot_ec->handle = ACPI_ROOT_OBJECT;
		boot_ec->handle = ACPI_ROOT_OBJECT;
	} else {
		printk(KERN_DEBUG PREFIX "Look up EC in DSDT\n");
		status = acpi_get_devices(ec_device_ids[0].id, ec_parse_device,
						boot_ec, NULL);
		if (ACPI_FAILURE(status))
			goto error;
	}


	ret = ec_install_handlers(boot_ec);
	ret = ec_install_handlers(boot_ec);
	if (!ret) {
	if (!ret) {