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

Commit 55e71edb authored by Mika Westerberg's avatar Mika Westerberg Committed by Wolfram Sang
Browse files

i2c: move ACPI helpers into the core



This follows what has already been done for the DeviceTree helpers. Move
the ACPI helpers from drivers/acpi/acpi_i2c.c to the I2C core and update
documentation accordingly.

This also solves a problem reported by Jerry Snitselaar that we can't build
the ACPI I2C helpers as a module.

Signed-off-by: default avatarMika Westerberg <mika.westerberg@linux.intel.com>
Acked-by: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
Signed-off-by: default avatarWolfram Sang <wsa@the-dreams.de>
parent 687b81d0
Loading
Loading
Loading
Loading
+3 −12
Original line number Diff line number Diff line
@@ -228,18 +228,9 @@ ACPI handle like:
I2C serial bus support
~~~~~~~~~~~~~~~~~~~~~~
The slaves behind I2C bus controller only need to add the ACPI IDs like
with the platform and SPI drivers. However the I2C bus controller driver
needs to call acpi_i2c_register_devices() after it has added the adapter.

An I2C bus (controller) driver does:

	...
	ret = i2c_add_numbered_adapter(adapter);
	if (ret)
		/* handle error */

	/* Enumerate the slave devices behind this bus via ACPI */
	acpi_i2c_register_devices(adapter);
with the platform and SPI drivers. The I2C core automatically enumerates
any slave devices behind the controller device once the adapter is
registered.

Below is an example of how to add ACPI support to the existing mpu3050
input driver:
+0 −6
Original line number Diff line number Diff line
@@ -180,12 +180,6 @@ config ACPI_DOCK
	  This driver supports ACPI-controlled docking stations and removable
	  drive bays such as the IBM Ultrabay and the Dell Module Bay.

config ACPI_I2C
	def_tristate I2C
	depends on I2C
	help
	  ACPI I2C enumeration support.

config ACPI_PROCESSOR
	tristate "Processor"
	select THERMAL
+0 −1
Original line number Diff line number Diff line
@@ -73,7 +73,6 @@ obj-$(CONFIG_ACPI_HED) += hed.o
obj-$(CONFIG_ACPI_EC_DEBUGFS)	+= ec_sys.o
obj-$(CONFIG_ACPI_CUSTOM_METHOD)+= custom_method.o
obj-$(CONFIG_ACPI_BGRT)		+= bgrt.o
obj-$(CONFIG_ACPI_I2C)		+= acpi_i2c.o

# processor has its own "processor." module_param namespace
processor-y			:= processor_driver.o processor_throttling.o

drivers/acpi/acpi_i2c.c

deleted100644 → 0
+0 −103
Original line number Diff line number Diff line
/*
 * ACPI I2C enumeration support
 *
 * Copyright (C) 2012, Intel Corporation
 * Author: Mika Westerberg <mika.westerberg@linux.intel.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

#include <linux/acpi.h>
#include <linux/device.h>
#include <linux/export.h>
#include <linux/i2c.h>
#include <linux/ioport.h>

ACPI_MODULE_NAME("i2c");

static int acpi_i2c_add_resource(struct acpi_resource *ares, void *data)
{
	struct i2c_board_info *info = data;

	if (ares->type == ACPI_RESOURCE_TYPE_SERIAL_BUS) {
		struct acpi_resource_i2c_serialbus *sb;

		sb = &ares->data.i2c_serial_bus;
		if (sb->type == ACPI_RESOURCE_SERIAL_TYPE_I2C) {
			info->addr = sb->slave_address;
			if (sb->access_mode == ACPI_I2C_10BIT_MODE)
				info->flags |= I2C_CLIENT_TEN;
		}
	} else if (info->irq < 0) {
		struct resource r;

		if (acpi_dev_resource_interrupt(ares, 0, &r))
			info->irq = r.start;
	}

	/* Tell the ACPI core to skip this resource */
	return 1;
}

static acpi_status acpi_i2c_add_device(acpi_handle handle, u32 level,
				       void *data, void **return_value)
{
	struct i2c_adapter *adapter = data;
	struct list_head resource_list;
	struct i2c_board_info info;
	struct acpi_device *adev;
	int ret;

	if (acpi_bus_get_device(handle, &adev))
		return AE_OK;
	if (acpi_bus_get_status(adev) || !adev->status.present)
		return AE_OK;

	memset(&info, 0, sizeof(info));
	info.acpi_node.handle = handle;
	info.irq = -1;

	INIT_LIST_HEAD(&resource_list);
	ret = acpi_dev_get_resources(adev, &resource_list,
				     acpi_i2c_add_resource, &info);
	acpi_dev_free_resource_list(&resource_list);

	if (ret < 0 || !info.addr)
		return AE_OK;

	strlcpy(info.type, dev_name(&adev->dev), sizeof(info.type));
	if (!i2c_new_device(adapter, &info)) {
		dev_err(&adapter->dev,
			"failed to add I2C device %s from ACPI\n",
			dev_name(&adev->dev));
	}

	return AE_OK;
}

/**
 * acpi_i2c_register_devices - enumerate I2C slave devices behind adapter
 * @adapter: pointer to adapter
 *
 * Enumerate all I2C slave devices behind this adapter by walking the ACPI
 * namespace. When a device is found it will be added to the Linux device
 * model and bound to the corresponding ACPI handle.
 */
void acpi_i2c_register_devices(struct i2c_adapter *adapter)
{
	acpi_handle handle;
	acpi_status status;

	handle = ACPI_HANDLE(adapter->dev.parent);
	if (!handle)
		return;

	status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, 1,
				     acpi_i2c_add_device, NULL,
				     adapter, NULL);
	if (ACPI_FAILURE(status))
		dev_warn(&adapter->dev, "failed to enumerate I2C slaves\n");
}
EXPORT_SYMBOL_GPL(acpi_i2c_register_devices);
+0 −1
Original line number Diff line number Diff line
@@ -171,7 +171,6 @@ static int dw_i2c_probe(struct platform_device *pdev)
		dev_err(&pdev->dev, "failure adding adapter\n");
		return r;
	}
	acpi_i2c_register_devices(adap);

	pm_runtime_set_autosuspend_delay(&pdev->dev, 1000);
	pm_runtime_use_autosuspend(&pdev->dev);
Loading