acpi_i2c.c 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. /*
  2. * ACPI I2C enumeration support
  3. *
  4. * Copyright (C) 2012, Intel Corporation
  5. * Author: Mika Westerberg <mika.westerberg@linux.intel.com>
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License version 2 as
  9. * published by the Free Software Foundation.
  10. */
  11. #include <linux/acpi.h>
  12. #include <linux/device.h>
  13. #include <linux/export.h>
  14. #include <linux/i2c.h>
  15. #include <linux/ioport.h>
  16. ACPI_MODULE_NAME("i2c");
  17. static int acpi_i2c_add_resource(struct acpi_resource *ares, void *data)
  18. {
  19. struct i2c_board_info *info = data;
  20. if (ares->type == ACPI_RESOURCE_TYPE_SERIAL_BUS) {
  21. struct acpi_resource_i2c_serialbus *sb;
  22. sb = &ares->data.i2c_serial_bus;
  23. if (sb->type == ACPI_RESOURCE_SERIAL_TYPE_I2C) {
  24. info->addr = sb->slave_address;
  25. if (sb->access_mode == ACPI_I2C_10BIT_MODE)
  26. info->flags |= I2C_CLIENT_TEN;
  27. }
  28. } else if (info->irq < 0) {
  29. struct resource r;
  30. if (acpi_dev_resource_interrupt(ares, 0, &r))
  31. info->irq = r.start;
  32. }
  33. /* Tell the ACPI core to skip this resource */
  34. return 1;
  35. }
  36. static acpi_status acpi_i2c_add_device(acpi_handle handle, u32 level,
  37. void *data, void **return_value)
  38. {
  39. struct i2c_adapter *adapter = data;
  40. struct list_head resource_list;
  41. struct i2c_board_info info;
  42. struct acpi_device *adev;
  43. int ret;
  44. if (acpi_bus_get_device(handle, &adev))
  45. return AE_OK;
  46. if (acpi_bus_get_status(adev) || !adev->status.present)
  47. return AE_OK;
  48. memset(&info, 0, sizeof(info));
  49. info.acpi_node.handle = handle;
  50. info.irq = -1;
  51. INIT_LIST_HEAD(&resource_list);
  52. ret = acpi_dev_get_resources(adev, &resource_list,
  53. acpi_i2c_add_resource, &info);
  54. acpi_dev_free_resource_list(&resource_list);
  55. if (ret < 0 || !info.addr)
  56. return AE_OK;
  57. strlcpy(info.type, dev_name(&adev->dev), sizeof(info.type));
  58. if (!i2c_new_device(adapter, &info)) {
  59. dev_err(&adapter->dev,
  60. "failed to add I2C device %s from ACPI\n",
  61. dev_name(&adev->dev));
  62. }
  63. return AE_OK;
  64. }
  65. /**
  66. * acpi_i2c_register_devices - enumerate I2C slave devices behind adapter
  67. * @adapter: pointer to adapter
  68. *
  69. * Enumerate all I2C slave devices behind this adapter by walking the ACPI
  70. * namespace. When a device is found it will be added to the Linux device
  71. * model and bound to the corresponding ACPI handle.
  72. */
  73. void acpi_i2c_register_devices(struct i2c_adapter *adapter)
  74. {
  75. acpi_handle handle;
  76. acpi_status status;
  77. handle = ACPI_HANDLE(&adapter->dev);
  78. if (!handle)
  79. return;
  80. status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, 1,
  81. acpi_i2c_add_device, NULL,
  82. adapter, NULL);
  83. if (ACPI_FAILURE(status))
  84. dev_warn(&adapter->dev, "failed to enumerate I2C slaves\n");
  85. }
  86. EXPORT_SYMBOL_GPL(acpi_i2c_register_devices);