diff options
Diffstat (limited to 'drivers/i2c/i2c-core.c')
-rw-r--r-- | drivers/i2c/i2c-core.c | 107 |
1 files changed, 12 insertions, 95 deletions
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index 66aa83b99383..632057a44615 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c | |||
@@ -1097,101 +1097,6 @@ EXPORT_SYMBOL(of_find_i2c_adapter_by_node); | |||
1097 | static void of_i2c_register_devices(struct i2c_adapter *adap) { } | 1097 | static void of_i2c_register_devices(struct i2c_adapter *adap) { } |
1098 | #endif /* CONFIG_OF */ | 1098 | #endif /* CONFIG_OF */ |
1099 | 1099 | ||
1100 | /* ACPI support code */ | ||
1101 | |||
1102 | #if IS_ENABLED(CONFIG_ACPI) | ||
1103 | static int acpi_i2c_add_resource(struct acpi_resource *ares, void *data) | ||
1104 | { | ||
1105 | struct i2c_board_info *info = data; | ||
1106 | |||
1107 | if (ares->type == ACPI_RESOURCE_TYPE_SERIAL_BUS) { | ||
1108 | struct acpi_resource_i2c_serialbus *sb; | ||
1109 | |||
1110 | sb = &ares->data.i2c_serial_bus; | ||
1111 | if (sb->type == ACPI_RESOURCE_SERIAL_TYPE_I2C) { | ||
1112 | info->addr = sb->slave_address; | ||
1113 | if (sb->access_mode == ACPI_I2C_10BIT_MODE) | ||
1114 | info->flags |= I2C_CLIENT_TEN; | ||
1115 | } | ||
1116 | } else if (info->irq < 0) { | ||
1117 | struct resource r; | ||
1118 | |||
1119 | if (acpi_dev_resource_interrupt(ares, 0, &r)) | ||
1120 | info->irq = r.start; | ||
1121 | } | ||
1122 | |||
1123 | /* Tell the ACPI core to skip this resource */ | ||
1124 | return 1; | ||
1125 | } | ||
1126 | |||
1127 | static acpi_status acpi_i2c_add_device(acpi_handle handle, u32 level, | ||
1128 | void *data, void **return_value) | ||
1129 | { | ||
1130 | struct i2c_adapter *adapter = data; | ||
1131 | struct list_head resource_list; | ||
1132 | struct i2c_board_info info; | ||
1133 | struct acpi_device *adev; | ||
1134 | int ret; | ||
1135 | |||
1136 | if (acpi_bus_get_device(handle, &adev)) | ||
1137 | return AE_OK; | ||
1138 | if (acpi_bus_get_status(adev) || !adev->status.present) | ||
1139 | return AE_OK; | ||
1140 | |||
1141 | memset(&info, 0, sizeof(info)); | ||
1142 | info.acpi_node.companion = adev; | ||
1143 | info.irq = -1; | ||
1144 | |||
1145 | INIT_LIST_HEAD(&resource_list); | ||
1146 | ret = acpi_dev_get_resources(adev, &resource_list, | ||
1147 | acpi_i2c_add_resource, &info); | ||
1148 | acpi_dev_free_resource_list(&resource_list); | ||
1149 | |||
1150 | if (ret < 0 || !info.addr) | ||
1151 | return AE_OK; | ||
1152 | |||
1153 | adev->power.flags.ignore_parent = true; | ||
1154 | strlcpy(info.type, dev_name(&adev->dev), sizeof(info.type)); | ||
1155 | if (!i2c_new_device(adapter, &info)) { | ||
1156 | adev->power.flags.ignore_parent = false; | ||
1157 | dev_err(&adapter->dev, | ||
1158 | "failed to add I2C device %s from ACPI\n", | ||
1159 | dev_name(&adev->dev)); | ||
1160 | } | ||
1161 | |||
1162 | return AE_OK; | ||
1163 | } | ||
1164 | |||
1165 | /** | ||
1166 | * acpi_i2c_register_devices - enumerate I2C slave devices behind adapter | ||
1167 | * @adap: pointer to adapter | ||
1168 | * | ||
1169 | * Enumerate all I2C slave devices behind this adapter by walking the ACPI | ||
1170 | * namespace. When a device is found it will be added to the Linux device | ||
1171 | * model and bound to the corresponding ACPI handle. | ||
1172 | */ | ||
1173 | static void acpi_i2c_register_devices(struct i2c_adapter *adap) | ||
1174 | { | ||
1175 | acpi_handle handle; | ||
1176 | acpi_status status; | ||
1177 | |||
1178 | if (!adap->dev.parent) | ||
1179 | return; | ||
1180 | |||
1181 | handle = ACPI_HANDLE(adap->dev.parent); | ||
1182 | if (!handle) | ||
1183 | return; | ||
1184 | |||
1185 | status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, 1, | ||
1186 | acpi_i2c_add_device, NULL, | ||
1187 | adap, NULL); | ||
1188 | if (ACPI_FAILURE(status)) | ||
1189 | dev_warn(&adap->dev, "failed to enumerate I2C slaves\n"); | ||
1190 | } | ||
1191 | #else | ||
1192 | static inline void acpi_i2c_register_devices(struct i2c_adapter *adap) {} | ||
1193 | #endif /* CONFIG_ACPI */ | ||
1194 | |||
1195 | static int i2c_do_add_adapter(struct i2c_driver *driver, | 1100 | static int i2c_do_add_adapter(struct i2c_driver *driver, |
1196 | struct i2c_adapter *adap) | 1101 | struct i2c_adapter *adap) |
1197 | { | 1102 | { |
@@ -1298,6 +1203,7 @@ exit_recovery: | |||
1298 | /* create pre-declared device nodes */ | 1203 | /* create pre-declared device nodes */ |
1299 | of_i2c_register_devices(adap); | 1204 | of_i2c_register_devices(adap); |
1300 | acpi_i2c_register_devices(adap); | 1205 | acpi_i2c_register_devices(adap); |
1206 | acpi_i2c_install_space_handler(adap); | ||
1301 | 1207 | ||
1302 | if (adap->nr < __i2c_first_dynamic_bus_num) | 1208 | if (adap->nr < __i2c_first_dynamic_bus_num) |
1303 | i2c_scan_static_board_info(adap); | 1209 | i2c_scan_static_board_info(adap); |
@@ -1471,6 +1377,7 @@ void i2c_del_adapter(struct i2c_adapter *adap) | |||
1471 | return; | 1377 | return; |
1472 | } | 1378 | } |
1473 | 1379 | ||
1380 | acpi_i2c_remove_space_handler(adap); | ||
1474 | /* Tell drivers about this removal */ | 1381 | /* Tell drivers about this removal */ |
1475 | mutex_lock(&core_lock); | 1382 | mutex_lock(&core_lock); |
1476 | bus_for_each_drv(&i2c_bus_type, NULL, adap, | 1383 | bus_for_each_drv(&i2c_bus_type, NULL, adap, |
@@ -2013,6 +1920,16 @@ static int i2c_detect(struct i2c_adapter *adapter, struct i2c_driver *driver) | |||
2013 | if (!driver->detect || !address_list) | 1920 | if (!driver->detect || !address_list) |
2014 | return 0; | 1921 | return 0; |
2015 | 1922 | ||
1923 | /* Warn that the adapter lost class based instantiation */ | ||
1924 | if (adapter->class == I2C_CLASS_DEPRECATED) { | ||
1925 | dev_dbg(&adapter->dev, | ||
1926 | "This adapter dropped support for I2C classes and " | ||
1927 | "won't auto-detect %s devices anymore. If you need it, check " | ||
1928 | "'Documentation/i2c/instantiating-devices' for alternatives.\n", | ||
1929 | driver->driver.name); | ||
1930 | return 0; | ||
1931 | } | ||
1932 | |||
2016 | /* Stop here if the classes do not match */ | 1933 | /* Stop here if the classes do not match */ |
2017 | if (!(adapter->class & driver->class)) | 1934 | if (!(adapter->class & driver->class)) |
2018 | return 0; | 1935 | return 0; |