int acpi_scan_add_handler(struct acpi_scan_handler *handler)
{
- if (!handler || !handler->attach)
+ if (!handler)
return -EINVAL;
list_add_tail(&handler->list_node, &acpi_scan_handlers_list);
return AE_OK;
}
+static int acpi_check_spi_i2c_slave(struct acpi_resource *ares, void *data)
+{
+ bool *is_spi_i2c_slave_p = data;
+
+ if (ares->type != ACPI_RESOURCE_TYPE_SERIAL_BUS)
+ return 1;
+
+ /*
+ * devices that are connected to UART still need to be enumerated to
+ * platform bus
+ */
+ if (ares->data.common_serial_bus.type != ACPI_RESOURCE_SERIAL_TYPE_UART)
+ *is_spi_i2c_slave_p = true;
+
+ /* no need to do more checking */
+ return -1;
+}
+
+static void acpi_default_enumeration(struct acpi_device *device)
+{
+ struct list_head resource_list;
+ bool is_spi_i2c_slave = false;
+
+ if (!device->pnp.type.platform_id || device->handler)
+ return;
+
+ /*
+ * Do not enemerate SPI/I2C slaves as they will be enuerated by their
+ * respective parents.
+ */
+ INIT_LIST_HEAD(&resource_list);
+ acpi_dev_get_resources(device, &resource_list, acpi_check_spi_i2c_slave,
+ &is_spi_i2c_slave);
+ acpi_dev_free_resource_list(&resource_list);
+ if (!is_spi_i2c_slave)
+ acpi_create_platform_device(device);
+}
+
static int acpi_scan_attach_handler(struct acpi_device *device)
{
struct acpi_hardware_id *hwid;
handler = acpi_scan_match_handler(hwid->id, &devid);
if (handler) {
+ if (!handler->attach) {
+ device->pnp.type.platform_id = 0;
+ continue;
+ }
device->handler = handler;
ret = handler->attach(device, devid);
if (ret > 0)
break;
}
}
+ if (!ret)
+ acpi_default_enumeration(device);
+
return ret;
}
acpi_pci_root_init();
acpi_pci_link_init();
acpi_processor_init();
- acpi_platform_init();
acpi_lpss_init();
acpi_cmos_rtc_init();
acpi_container_init();
if (result)
goto out;
- result = acpi_bus_scan_fixed();
- if (result) {
- acpi_detach_data(acpi_root->handle, acpi_scan_drop_device);
- acpi_device_del(acpi_root);
- put_device(&acpi_root->dev);
- goto out;
+ /* Fixed feature devices do not exist on HW-reduced platform */
+ if (!acpi_gbl_reduced_hardware) {
+ result = acpi_bus_scan_fixed();
+ if (result) {
+ acpi_detach_data(acpi_root->handle,
+ acpi_scan_drop_device);
+ acpi_device_del(acpi_root);
+ put_device(&acpi_root->dev);
+ goto out;
+ }
}
acpi_update_all_gpes();