Skip to content

Commit

Permalink
Merge branch 'acpi-enumeration'
Browse files Browse the repository at this point in the history
* acpi-enumeration:
  ACPI: remove unnecessary INIT_LIST_HEAD
  ACPI / platform: include missed header into acpi_platform.c
  platform / ACPI: Attach/detach ACPI PM during probe/remove/shutdown
  mmc: sdhci-acpi: add SDHCI ACPI driver
  ACPI: add SDHCI to ACPI platform devices
  ACPI / PNP: skip ACPI device nodes associated with physical nodes already
  i2c / ACPI: add ACPI enumeration support
  ACPI / platform: Initialize ACPI handles of platform devices in advance
  ACPI / driver core: Introduce struct acpi_dev_node and related macros
  ACPI: Allow ACPI handles of devices to be initialized in advance
  ACPI / resources: Use AE_CTRL_TERMINATE to terminate resources walks
  ACPI: Centralized processing of ACPI device resources
  ACPI / platform: Use common ACPI device resource parsing routines
  ACPI: Move device resources interpretation code from PNP to ACPI core
  ACPI / platform: use ACPI device name instead of _HID._UID
  ACPI: Add support for platform bus type
  ACPI / ia64: Export acpi_[un]register_gsi()
  ACPI / x86: Export acpi_[un]register_gsi()
  ACPI: Provide generic functions for matching ACPI device nodes
  driver core / ACPI: Move ACPI support to core device and driver types
  • Loading branch information
Rafael J. Wysocki committed Nov 29, 2012
2 parents acd8443 + 752cad7 commit bcacbdb
Show file tree
Hide file tree
Showing 27 changed files with 1,326 additions and 301 deletions.
3 changes: 0 additions & 3 deletions arch/ia64/include/asm/device.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,6 @@
#define _ASM_IA64_DEVICE_H

struct dev_archdata {
#ifdef CONFIG_ACPI
void *acpi_handle;
#endif
#ifdef CONFIG_INTEL_IOMMU
void *iommu; /* hook for IOMMU specific extension */
#endif
Expand Down
2 changes: 2 additions & 0 deletions arch/ia64/kernel/acpi.c
Original file line number Diff line number Diff line change
Expand Up @@ -633,6 +633,7 @@ int acpi_register_gsi(struct device *dev, u32 gsi, int triggering, int polarity)
ACPI_EDGE_SENSITIVE) ? IOSAPIC_EDGE :
IOSAPIC_LEVEL);
}
EXPORT_SYMBOL_GPL(acpi_register_gsi);

void acpi_unregister_gsi(u32 gsi)
{
Expand All @@ -644,6 +645,7 @@ void acpi_unregister_gsi(u32 gsi)

iosapic_unregister_intr(gsi);
}
EXPORT_SYMBOL_GPL(acpi_unregister_gsi);

static int __init acpi_parse_fadt(struct acpi_table_header *table)
{
Expand Down
3 changes: 0 additions & 3 deletions arch/x86/include/asm/device.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,6 @@
#define _ASM_X86_DEVICE_H

struct dev_archdata {
#ifdef CONFIG_ACPI
void *acpi_handle;
#endif
#ifdef CONFIG_X86_DEV_DMA_OPS
struct dma_map_ops *dma_ops;
#endif
Expand Down
6 changes: 6 additions & 0 deletions arch/x86/kernel/acpi/boot.c
Original file line number Diff line number Diff line change
Expand Up @@ -574,6 +574,12 @@ int acpi_register_gsi(struct device *dev, u32 gsi, int trigger, int polarity)

return irq;
}
EXPORT_SYMBOL_GPL(acpi_register_gsi);

void acpi_unregister_gsi(u32 gsi)
{
}
EXPORT_SYMBOL_GPL(acpi_unregister_gsi);

void __init acpi_set_irq_model_pic(void)
{
Expand Down
6 changes: 6 additions & 0 deletions drivers/acpi/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,12 @@ 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
Expand Down
3 changes: 3 additions & 0 deletions drivers/acpi/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,12 @@ acpi-$(CONFIG_ACPI_SLEEP) += proc.o
#
acpi-y += bus.o glue.o
acpi-y += scan.o
acpi-y += resource.o
acpi-y += processor_core.o
acpi-y += ec.o
acpi-$(CONFIG_ACPI_DOCK) += dock.o
acpi-y += pci_root.o pci_link.o pci_irq.o pci_bind.o
acpi-y += acpi_platform.o
acpi-y += power.o
acpi-y += event.o
acpi-y += sysfs.o
Expand Down Expand Up @@ -68,6 +70,7 @@ 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
Expand Down
103 changes: 103 additions & 0 deletions drivers/acpi/acpi_i2c.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
/*
* 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);
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);
104 changes: 104 additions & 0 deletions drivers/acpi/acpi_platform.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
/*
* ACPI support for platform bus type.
*
* Copyright (C) 2012, Intel Corporation
* Authors: Mika Westerberg <mika.westerberg@linux.intel.com>
* Mathias Nyman <mathias.nyman@linux.intel.com>
* Rafael J. Wysocki <rafael.j.wysocki@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/kernel.h>
#include <linux/module.h>
#include <linux/platform_device.h>

#include "internal.h"

ACPI_MODULE_NAME("platform");

/**
* acpi_create_platform_device - Create platform device for ACPI device node
* @adev: ACPI device node to create a platform device for.
*
* Check if the given @adev can be represented as a platform device and, if
* that's the case, create and register a platform device, populate its common
* resources and returns a pointer to it. Otherwise, return %NULL.
*
* The platform device's name will be taken from the @adev's _HID and _UID.
*/
struct platform_device *acpi_create_platform_device(struct acpi_device *adev)
{
struct platform_device *pdev = NULL;
struct acpi_device *acpi_parent;
struct platform_device_info pdevinfo;
struct resource_list_entry *rentry;
struct list_head resource_list;
struct resource *resources;
int count;

/* If the ACPI node already has a physical device attached, skip it. */
if (adev->physical_node_count)
return NULL;

INIT_LIST_HEAD(&resource_list);
count = acpi_dev_get_resources(adev, &resource_list, NULL, NULL);
if (count <= 0)
return NULL;

resources = kmalloc(count * sizeof(struct resource), GFP_KERNEL);
if (!resources) {
dev_err(&adev->dev, "No memory for resources\n");
acpi_dev_free_resource_list(&resource_list);
return NULL;
}
count = 0;
list_for_each_entry(rentry, &resource_list, node)
resources[count++] = rentry->res;

acpi_dev_free_resource_list(&resource_list);

memset(&pdevinfo, 0, sizeof(pdevinfo));
/*
* If the ACPI node has a parent and that parent has a physical device
* attached to it, that physical device should be the parent of the
* platform device we are about to create.
*/
pdevinfo.parent = NULL;
acpi_parent = adev->parent;
if (acpi_parent) {
struct acpi_device_physical_node *entry;
struct list_head *list;

mutex_lock(&acpi_parent->physical_node_lock);
list = &acpi_parent->physical_node_list;
if (!list_empty(list)) {
entry = list_first_entry(list,
struct acpi_device_physical_node,
node);
pdevinfo.parent = entry->dev;
}
mutex_unlock(&acpi_parent->physical_node_lock);
}
pdevinfo.name = dev_name(&adev->dev);
pdevinfo.id = -1;
pdevinfo.res = resources;
pdevinfo.num_res = count;
pdevinfo.acpi_node.handle = adev->handle;
pdev = platform_device_register_full(&pdevinfo);
if (IS_ERR(pdev)) {
dev_err(&adev->dev, "platform device creation failed: %ld\n",
PTR_ERR(pdev));
pdev = NULL;
} else {
dev_dbg(&adev->dev, "created platform device %s\n",
dev_name(&pdev->dev));
}

kfree(resources);
return pdev;
}
Loading

0 comments on commit bcacbdb

Please sign in to comment.