12874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later 253f8f7c5SWolfram Sang /* 353f8f7c5SWolfram Sang * Linux I2C core ACPI support code 453f8f7c5SWolfram Sang * 553f8f7c5SWolfram Sang * Copyright (C) 2014 Intel Corp, Author: Lan Tianyu <tianyu.lan@intel.com> 653f8f7c5SWolfram Sang */ 753f8f7c5SWolfram Sang 853f8f7c5SWolfram Sang #include <linux/acpi.h> 953f8f7c5SWolfram Sang #include <linux/device.h> 1053f8f7c5SWolfram Sang #include <linux/err.h> 1153f8f7c5SWolfram Sang #include <linux/i2c.h> 1253f8f7c5SWolfram Sang #include <linux/list.h> 1353f8f7c5SWolfram Sang #include <linux/module.h> 1453f8f7c5SWolfram Sang #include <linux/slab.h> 1553f8f7c5SWolfram Sang 1653f8f7c5SWolfram Sang #include "i2c-core.h" 1753f8f7c5SWolfram Sang 1853f8f7c5SWolfram Sang struct i2c_acpi_handler_data { 1953f8f7c5SWolfram Sang struct acpi_connection_info info; 2053f8f7c5SWolfram Sang struct i2c_adapter *adapter; 2153f8f7c5SWolfram Sang }; 2253f8f7c5SWolfram Sang 2353f8f7c5SWolfram Sang struct gsb_buffer { 2453f8f7c5SWolfram Sang u8 status; 2553f8f7c5SWolfram Sang u8 len; 2653f8f7c5SWolfram Sang union { 2753f8f7c5SWolfram Sang u16 wdata; 2853f8f7c5SWolfram Sang u8 bdata; 2953f8f7c5SWolfram Sang u8 data[0]; 3053f8f7c5SWolfram Sang }; 3153f8f7c5SWolfram Sang } __packed; 3253f8f7c5SWolfram Sang 3353f8f7c5SWolfram Sang struct i2c_acpi_lookup { 3453f8f7c5SWolfram Sang struct i2c_board_info *info; 3553f8f7c5SWolfram Sang acpi_handle adapter_handle; 3653f8f7c5SWolfram Sang acpi_handle device_handle; 3753f8f7c5SWolfram Sang acpi_handle search_handle; 3853f8f7c5SWolfram Sang int n; 3953f8f7c5SWolfram Sang int index; 4053f8f7c5SWolfram Sang u32 speed; 4153f8f7c5SWolfram Sang u32 min_speed; 427574c0dbSHans de Goede u32 force_speed; 4353f8f7c5SWolfram Sang }; 4453f8f7c5SWolfram Sang 450d5102feSAndy Shevchenko /** 460d5102feSAndy Shevchenko * i2c_acpi_get_i2c_resource - Gets I2cSerialBus resource if type matches 470d5102feSAndy Shevchenko * @ares: ACPI resource 480d5102feSAndy Shevchenko * @i2c: Pointer to I2cSerialBus resource will be returned here 490d5102feSAndy Shevchenko * 500d5102feSAndy Shevchenko * Checks if the given ACPI resource is of type I2cSerialBus. 510d5102feSAndy Shevchenko * In this case, returns a pointer to it to the caller. 520d5102feSAndy Shevchenko * 530d5102feSAndy Shevchenko * Returns true if resource type is of I2cSerialBus, otherwise false. 540d5102feSAndy Shevchenko */ 550d5102feSAndy Shevchenko bool i2c_acpi_get_i2c_resource(struct acpi_resource *ares, 560d5102feSAndy Shevchenko struct acpi_resource_i2c_serialbus **i2c) 570d5102feSAndy Shevchenko { 580d5102feSAndy Shevchenko struct acpi_resource_i2c_serialbus *sb; 590d5102feSAndy Shevchenko 600d5102feSAndy Shevchenko if (ares->type != ACPI_RESOURCE_TYPE_SERIAL_BUS) 610d5102feSAndy Shevchenko return false; 620d5102feSAndy Shevchenko 630d5102feSAndy Shevchenko sb = &ares->data.i2c_serial_bus; 640d5102feSAndy Shevchenko if (sb->type != ACPI_RESOURCE_SERIAL_TYPE_I2C) 650d5102feSAndy Shevchenko return false; 660d5102feSAndy Shevchenko 670d5102feSAndy Shevchenko *i2c = sb; 680d5102feSAndy Shevchenko return true; 690d5102feSAndy Shevchenko } 700d5102feSAndy Shevchenko EXPORT_SYMBOL_GPL(i2c_acpi_get_i2c_resource); 710d5102feSAndy Shevchenko 7220a1b3acSHans de Goede static int i2c_acpi_resource_count(struct acpi_resource *ares, void *data) 7320a1b3acSHans de Goede { 7420a1b3acSHans de Goede struct acpi_resource_i2c_serialbus *sb; 7520a1b3acSHans de Goede int *count = data; 7620a1b3acSHans de Goede 7720a1b3acSHans de Goede if (i2c_acpi_get_i2c_resource(ares, &sb)) 7820a1b3acSHans de Goede *count = *count + 1; 7920a1b3acSHans de Goede 8020a1b3acSHans de Goede return 1; 8120a1b3acSHans de Goede } 8220a1b3acSHans de Goede 8320a1b3acSHans de Goede /** 8420a1b3acSHans de Goede * i2c_acpi_client_count - Count the number of I2cSerialBus resources 8520a1b3acSHans de Goede * @adev: ACPI device 8620a1b3acSHans de Goede * 8720a1b3acSHans de Goede * Returns the number of I2cSerialBus resources in the ACPI-device's 8820a1b3acSHans de Goede * resource-list; or a negative error code. 8920a1b3acSHans de Goede */ 9020a1b3acSHans de Goede int i2c_acpi_client_count(struct acpi_device *adev) 9120a1b3acSHans de Goede { 9220a1b3acSHans de Goede int ret, count = 0; 9320a1b3acSHans de Goede LIST_HEAD(r); 9420a1b3acSHans de Goede 9520a1b3acSHans de Goede ret = acpi_dev_get_resources(adev, &r, i2c_acpi_resource_count, &count); 9620a1b3acSHans de Goede if (ret < 0) 9720a1b3acSHans de Goede return ret; 9820a1b3acSHans de Goede 9920a1b3acSHans de Goede acpi_dev_free_resource_list(&r); 10020a1b3acSHans de Goede return count; 10120a1b3acSHans de Goede } 10220a1b3acSHans de Goede EXPORT_SYMBOL_GPL(i2c_acpi_client_count); 10320a1b3acSHans de Goede 10453f8f7c5SWolfram Sang static int i2c_acpi_fill_info(struct acpi_resource *ares, void *data) 10553f8f7c5SWolfram Sang { 10653f8f7c5SWolfram Sang struct i2c_acpi_lookup *lookup = data; 10753f8f7c5SWolfram Sang struct i2c_board_info *info = lookup->info; 10853f8f7c5SWolfram Sang struct acpi_resource_i2c_serialbus *sb; 10953f8f7c5SWolfram Sang acpi_status status; 11053f8f7c5SWolfram Sang 1110d5102feSAndy Shevchenko if (info->addr || !i2c_acpi_get_i2c_resource(ares, &sb)) 11253f8f7c5SWolfram Sang return 1; 11353f8f7c5SWolfram Sang 11453f8f7c5SWolfram Sang if (lookup->index != -1 && lookup->n++ != lookup->index) 11553f8f7c5SWolfram Sang return 1; 11653f8f7c5SWolfram Sang 11753f8f7c5SWolfram Sang status = acpi_get_handle(lookup->device_handle, 11853f8f7c5SWolfram Sang sb->resource_source.string_ptr, 11953f8f7c5SWolfram Sang &lookup->adapter_handle); 1205f59d6a1SAndy Shevchenko if (ACPI_FAILURE(status)) 12153f8f7c5SWolfram Sang return 1; 12253f8f7c5SWolfram Sang 12353f8f7c5SWolfram Sang info->addr = sb->slave_address; 12453f8f7c5SWolfram Sang lookup->speed = sb->connection_speed; 12553f8f7c5SWolfram Sang if (sb->access_mode == ACPI_I2C_10BIT_MODE) 12653f8f7c5SWolfram Sang info->flags |= I2C_CLIENT_TEN; 12753f8f7c5SWolfram Sang 12853f8f7c5SWolfram Sang return 1; 12953f8f7c5SWolfram Sang } 13053f8f7c5SWolfram Sang 1313a4991a9SHans de Goede static const struct acpi_device_id i2c_acpi_ignored_device_ids[] = { 1323a4991a9SHans de Goede /* 1333a4991a9SHans de Goede * ACPI video acpi_devices, which are handled by the acpi-video driver 1343a4991a9SHans de Goede * sometimes contain a SERIAL_TYPE_I2C ACPI resource, ignore these. 1353a4991a9SHans de Goede */ 1363a4991a9SHans de Goede { ACPI_VIDEO_HID, 0 }, 1373a4991a9SHans de Goede {} 1383a4991a9SHans de Goede }; 1393a4991a9SHans de Goede 14053f8f7c5SWolfram Sang static int i2c_acpi_do_lookup(struct acpi_device *adev, 14153f8f7c5SWolfram Sang struct i2c_acpi_lookup *lookup) 14253f8f7c5SWolfram Sang { 14353f8f7c5SWolfram Sang struct i2c_board_info *info = lookup->info; 14453f8f7c5SWolfram Sang struct list_head resource_list; 14553f8f7c5SWolfram Sang int ret; 14653f8f7c5SWolfram Sang 1474befedc0SArd Biesheuvel if (acpi_bus_get_status(adev) || !adev->status.present) 14853f8f7c5SWolfram Sang return -EINVAL; 14953f8f7c5SWolfram Sang 1503a4991a9SHans de Goede if (acpi_match_device_ids(adev, i2c_acpi_ignored_device_ids) == 0) 1513a4991a9SHans de Goede return -ENODEV; 1523a4991a9SHans de Goede 15353f8f7c5SWolfram Sang memset(info, 0, sizeof(*info)); 15453f8f7c5SWolfram Sang lookup->device_handle = acpi_device_handle(adev); 15553f8f7c5SWolfram Sang 15653f8f7c5SWolfram Sang /* Look up for I2cSerialBus resource */ 15753f8f7c5SWolfram Sang INIT_LIST_HEAD(&resource_list); 15853f8f7c5SWolfram Sang ret = acpi_dev_get_resources(adev, &resource_list, 15953f8f7c5SWolfram Sang i2c_acpi_fill_info, lookup); 16053f8f7c5SWolfram Sang acpi_dev_free_resource_list(&resource_list); 16153f8f7c5SWolfram Sang 16253f8f7c5SWolfram Sang if (ret < 0 || !info->addr) 16353f8f7c5SWolfram Sang return -EINVAL; 16453f8f7c5SWolfram Sang 16553f8f7c5SWolfram Sang return 0; 16653f8f7c5SWolfram Sang } 16753f8f7c5SWolfram Sang 168c2223ddcSCharles Keepax static int i2c_acpi_add_resource(struct acpi_resource *ares, void *data) 169c2223ddcSCharles Keepax { 170c2223ddcSCharles Keepax int *irq = data; 171c2223ddcSCharles Keepax struct resource r; 172c2223ddcSCharles Keepax 173c2223ddcSCharles Keepax if (*irq <= 0 && acpi_dev_resource_interrupt(ares, 0, &r)) 174c2223ddcSCharles Keepax *irq = i2c_dev_irq_from_resources(&r, 1); 175c2223ddcSCharles Keepax 176c2223ddcSCharles Keepax return 1; /* No need to add resource to the list */ 177c2223ddcSCharles Keepax } 178c2223ddcSCharles Keepax 17916c9db1dSCharles Keepax /** 18016c9db1dSCharles Keepax * i2c_acpi_get_irq - get device IRQ number from ACPI 18116c9db1dSCharles Keepax * @client: Pointer to the I2C client device 18216c9db1dSCharles Keepax * 18316c9db1dSCharles Keepax * Find the IRQ number used by a specific client device. 18416c9db1dSCharles Keepax * 18516c9db1dSCharles Keepax * Return: The IRQ number or an error code. 18616c9db1dSCharles Keepax */ 18716c9db1dSCharles Keepax int i2c_acpi_get_irq(struct i2c_client *client) 188a52e3b37SCharles Keepax { 18916c9db1dSCharles Keepax struct acpi_device *adev = ACPI_COMPANION(&client->dev); 190a52e3b37SCharles Keepax struct list_head resource_list; 191a52e3b37SCharles Keepax int irq = -ENOENT; 192a52e3b37SCharles Keepax int ret; 193a52e3b37SCharles Keepax 194a52e3b37SCharles Keepax INIT_LIST_HEAD(&resource_list); 195a52e3b37SCharles Keepax 196a52e3b37SCharles Keepax ret = acpi_dev_get_resources(adev, &resource_list, 197a52e3b37SCharles Keepax i2c_acpi_add_resource, &irq); 198a52e3b37SCharles Keepax if (ret < 0) 199a52e3b37SCharles Keepax return ret; 200a52e3b37SCharles Keepax 201a52e3b37SCharles Keepax acpi_dev_free_resource_list(&resource_list); 202a52e3b37SCharles Keepax 2038466b616SCharles Keepax if (irq == -ENOENT) 2048466b616SCharles Keepax irq = acpi_dev_gpio_irq_get(adev, 0); 2058466b616SCharles Keepax 206a52e3b37SCharles Keepax return irq; 207a52e3b37SCharles Keepax } 208a52e3b37SCharles Keepax 20953f8f7c5SWolfram Sang static int i2c_acpi_get_info(struct acpi_device *adev, 21053f8f7c5SWolfram Sang struct i2c_board_info *info, 21153f8f7c5SWolfram Sang struct i2c_adapter *adapter, 21253f8f7c5SWolfram Sang acpi_handle *adapter_handle) 21353f8f7c5SWolfram Sang { 21453f8f7c5SWolfram Sang struct i2c_acpi_lookup lookup; 21553f8f7c5SWolfram Sang int ret; 21653f8f7c5SWolfram Sang 21753f8f7c5SWolfram Sang memset(&lookup, 0, sizeof(lookup)); 21853f8f7c5SWolfram Sang lookup.info = info; 21953f8f7c5SWolfram Sang lookup.index = -1; 22053f8f7c5SWolfram Sang 2214befedc0SArd Biesheuvel if (acpi_device_enumerated(adev)) 2224befedc0SArd Biesheuvel return -EINVAL; 2234befedc0SArd Biesheuvel 22453f8f7c5SWolfram Sang ret = i2c_acpi_do_lookup(adev, &lookup); 22553f8f7c5SWolfram Sang if (ret) 22653f8f7c5SWolfram Sang return ret; 22753f8f7c5SWolfram Sang 22853f8f7c5SWolfram Sang if (adapter) { 22953f8f7c5SWolfram Sang /* The adapter must match the one in I2cSerialBus() connector */ 23053f8f7c5SWolfram Sang if (ACPI_HANDLE(&adapter->dev) != lookup.adapter_handle) 23153f8f7c5SWolfram Sang return -ENODEV; 23253f8f7c5SWolfram Sang } else { 23353f8f7c5SWolfram Sang struct acpi_device *adapter_adev; 23453f8f7c5SWolfram Sang 23553f8f7c5SWolfram Sang /* The adapter must be present */ 23653f8f7c5SWolfram Sang if (acpi_bus_get_device(lookup.adapter_handle, &adapter_adev)) 23753f8f7c5SWolfram Sang return -ENODEV; 23853f8f7c5SWolfram Sang if (acpi_bus_get_status(adapter_adev) || 23953f8f7c5SWolfram Sang !adapter_adev->status.present) 24053f8f7c5SWolfram Sang return -ENODEV; 24153f8f7c5SWolfram Sang } 24253f8f7c5SWolfram Sang 24353f8f7c5SWolfram Sang info->fwnode = acpi_fwnode_handle(adev); 24453f8f7c5SWolfram Sang if (adapter_handle) 24553f8f7c5SWolfram Sang *adapter_handle = lookup.adapter_handle; 24653f8f7c5SWolfram Sang 24753f8f7c5SWolfram Sang acpi_set_modalias(adev, dev_name(&adev->dev), info->type, 24853f8f7c5SWolfram Sang sizeof(info->type)); 24953f8f7c5SWolfram Sang 25053f8f7c5SWolfram Sang return 0; 25153f8f7c5SWolfram Sang } 25253f8f7c5SWolfram Sang 25353f8f7c5SWolfram Sang static void i2c_acpi_register_device(struct i2c_adapter *adapter, 25453f8f7c5SWolfram Sang struct acpi_device *adev, 25553f8f7c5SWolfram Sang struct i2c_board_info *info) 25653f8f7c5SWolfram Sang { 25753f8f7c5SWolfram Sang adev->power.flags.ignore_parent = true; 25853f8f7c5SWolfram Sang acpi_device_set_enumerated(adev); 25953f8f7c5SWolfram Sang 260785e21cfSHans de Goede if (IS_ERR(i2c_new_client_device(adapter, info))) 26153f8f7c5SWolfram Sang adev->power.flags.ignore_parent = false; 26253f8f7c5SWolfram Sang } 26353f8f7c5SWolfram Sang 26453f8f7c5SWolfram Sang static acpi_status i2c_acpi_add_device(acpi_handle handle, u32 level, 26553f8f7c5SWolfram Sang void *data, void **return_value) 26653f8f7c5SWolfram Sang { 26753f8f7c5SWolfram Sang struct i2c_adapter *adapter = data; 26853f8f7c5SWolfram Sang struct acpi_device *adev; 26953f8f7c5SWolfram Sang struct i2c_board_info info; 27053f8f7c5SWolfram Sang 27153f8f7c5SWolfram Sang if (acpi_bus_get_device(handle, &adev)) 27253f8f7c5SWolfram Sang return AE_OK; 27353f8f7c5SWolfram Sang 27453f8f7c5SWolfram Sang if (i2c_acpi_get_info(adev, &info, adapter, NULL)) 27553f8f7c5SWolfram Sang return AE_OK; 27653f8f7c5SWolfram Sang 27753f8f7c5SWolfram Sang i2c_acpi_register_device(adapter, adev, &info); 27853f8f7c5SWolfram Sang 27953f8f7c5SWolfram Sang return AE_OK; 28053f8f7c5SWolfram Sang } 28153f8f7c5SWolfram Sang 28253f8f7c5SWolfram Sang #define I2C_ACPI_MAX_SCAN_DEPTH 32 28353f8f7c5SWolfram Sang 28453f8f7c5SWolfram Sang /** 28553f8f7c5SWolfram Sang * i2c_acpi_register_devices - enumerate I2C slave devices behind adapter 28653f8f7c5SWolfram Sang * @adap: pointer to adapter 28753f8f7c5SWolfram Sang * 28853f8f7c5SWolfram Sang * Enumerate all I2C slave devices behind this adapter by walking the ACPI 28953f8f7c5SWolfram Sang * namespace. When a device is found it will be added to the Linux device 29053f8f7c5SWolfram Sang * model and bound to the corresponding ACPI handle. 29153f8f7c5SWolfram Sang */ 29253f8f7c5SWolfram Sang void i2c_acpi_register_devices(struct i2c_adapter *adap) 29353f8f7c5SWolfram Sang { 294a9e10e58SDaniel Scally struct acpi_device *adev; 29553f8f7c5SWolfram Sang acpi_status status; 29653f8f7c5SWolfram Sang 29753f8f7c5SWolfram Sang if (!has_acpi_companion(&adap->dev)) 29853f8f7c5SWolfram Sang return; 29953f8f7c5SWolfram Sang 30053f8f7c5SWolfram Sang status = acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, 30153f8f7c5SWolfram Sang I2C_ACPI_MAX_SCAN_DEPTH, 30253f8f7c5SWolfram Sang i2c_acpi_add_device, NULL, 30353f8f7c5SWolfram Sang adap, NULL); 30453f8f7c5SWolfram Sang if (ACPI_FAILURE(status)) 30553f8f7c5SWolfram Sang dev_warn(&adap->dev, "failed to enumerate I2C slaves\n"); 3068058d699SHans de Goede 3078058d699SHans de Goede if (!adap->dev.parent) 3088058d699SHans de Goede return; 3098058d699SHans de Goede 310a9e10e58SDaniel Scally adev = ACPI_COMPANION(adap->dev.parent); 311a9e10e58SDaniel Scally if (!adev) 3128058d699SHans de Goede return; 3138058d699SHans de Goede 314a9e10e58SDaniel Scally acpi_dev_clear_dependencies(adev); 31553f8f7c5SWolfram Sang } 31653f8f7c5SWolfram Sang 3177574c0dbSHans de Goede static const struct acpi_device_id i2c_acpi_force_400khz_device_ids[] = { 3187574c0dbSHans de Goede /* 3197574c0dbSHans de Goede * These Silead touchscreen controllers only work at 400KHz, for 3207574c0dbSHans de Goede * some reason they do not work at 100KHz. On some devices the ACPI 3217574c0dbSHans de Goede * tables list another device at their bus as only being capable 3227574c0dbSHans de Goede * of 100KHz, testing has shown that these other devices work fine 3237574c0dbSHans de Goede * at 400KHz (as can be expected of any recent i2c hw) so we force 3247574c0dbSHans de Goede * the speed of the bus to 400 KHz if a Silead device is present. 3257574c0dbSHans de Goede */ 3267574c0dbSHans de Goede { "MSSL1680", 0 }, 3277574c0dbSHans de Goede {} 3287574c0dbSHans de Goede }; 3297574c0dbSHans de Goede 33053f8f7c5SWolfram Sang static acpi_status i2c_acpi_lookup_speed(acpi_handle handle, u32 level, 33153f8f7c5SWolfram Sang void *data, void **return_value) 33253f8f7c5SWolfram Sang { 33353f8f7c5SWolfram Sang struct i2c_acpi_lookup *lookup = data; 33453f8f7c5SWolfram Sang struct acpi_device *adev; 33553f8f7c5SWolfram Sang 33653f8f7c5SWolfram Sang if (acpi_bus_get_device(handle, &adev)) 33753f8f7c5SWolfram Sang return AE_OK; 33853f8f7c5SWolfram Sang 33953f8f7c5SWolfram Sang if (i2c_acpi_do_lookup(adev, lookup)) 34053f8f7c5SWolfram Sang return AE_OK; 34153f8f7c5SWolfram Sang 34253f8f7c5SWolfram Sang if (lookup->search_handle != lookup->adapter_handle) 34353f8f7c5SWolfram Sang return AE_OK; 34453f8f7c5SWolfram Sang 34553f8f7c5SWolfram Sang if (lookup->speed <= lookup->min_speed) 34653f8f7c5SWolfram Sang lookup->min_speed = lookup->speed; 34753f8f7c5SWolfram Sang 3487574c0dbSHans de Goede if (acpi_match_device_ids(adev, i2c_acpi_force_400khz_device_ids) == 0) 349e6282fc6SAndy Shevchenko lookup->force_speed = I2C_MAX_FAST_MODE_FREQ; 3507574c0dbSHans de Goede 35153f8f7c5SWolfram Sang return AE_OK; 35253f8f7c5SWolfram Sang } 35353f8f7c5SWolfram Sang 35453f8f7c5SWolfram Sang /** 35553f8f7c5SWolfram Sang * i2c_acpi_find_bus_speed - find I2C bus speed from ACPI 35653f8f7c5SWolfram Sang * @dev: The device owning the bus 35753f8f7c5SWolfram Sang * 35853f8f7c5SWolfram Sang * Find the I2C bus speed by walking the ACPI namespace for all I2C slaves 35953f8f7c5SWolfram Sang * devices connected to this bus and use the speed of slowest device. 36053f8f7c5SWolfram Sang * 36153f8f7c5SWolfram Sang * Returns the speed in Hz or zero 36253f8f7c5SWolfram Sang */ 36353f8f7c5SWolfram Sang u32 i2c_acpi_find_bus_speed(struct device *dev) 36453f8f7c5SWolfram Sang { 36553f8f7c5SWolfram Sang struct i2c_acpi_lookup lookup; 36653f8f7c5SWolfram Sang struct i2c_board_info dummy; 36753f8f7c5SWolfram Sang acpi_status status; 36853f8f7c5SWolfram Sang 36953f8f7c5SWolfram Sang if (!has_acpi_companion(dev)) 37053f8f7c5SWolfram Sang return 0; 37153f8f7c5SWolfram Sang 37253f8f7c5SWolfram Sang memset(&lookup, 0, sizeof(lookup)); 37353f8f7c5SWolfram Sang lookup.search_handle = ACPI_HANDLE(dev); 37453f8f7c5SWolfram Sang lookup.min_speed = UINT_MAX; 37553f8f7c5SWolfram Sang lookup.info = &dummy; 37653f8f7c5SWolfram Sang lookup.index = -1; 37753f8f7c5SWolfram Sang 37853f8f7c5SWolfram Sang status = acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, 37953f8f7c5SWolfram Sang I2C_ACPI_MAX_SCAN_DEPTH, 38053f8f7c5SWolfram Sang i2c_acpi_lookup_speed, NULL, 38153f8f7c5SWolfram Sang &lookup, NULL); 38253f8f7c5SWolfram Sang 38353f8f7c5SWolfram Sang if (ACPI_FAILURE(status)) { 38453f8f7c5SWolfram Sang dev_warn(dev, "unable to find I2C bus speed from ACPI\n"); 38553f8f7c5SWolfram Sang return 0; 38653f8f7c5SWolfram Sang } 38753f8f7c5SWolfram Sang 3887574c0dbSHans de Goede if (lookup.force_speed) { 3897574c0dbSHans de Goede if (lookup.force_speed != lookup.min_speed) 3907574c0dbSHans de Goede dev_warn(dev, FW_BUG "DSDT uses known not-working I2C bus speed %d, forcing it to %d\n", 3917574c0dbSHans de Goede lookup.min_speed, lookup.force_speed); 3927574c0dbSHans de Goede return lookup.force_speed; 3937574c0dbSHans de Goede } else if (lookup.min_speed != UINT_MAX) { 3947574c0dbSHans de Goede return lookup.min_speed; 3957574c0dbSHans de Goede } else { 3967574c0dbSHans de Goede return 0; 3977574c0dbSHans de Goede } 39853f8f7c5SWolfram Sang } 39953f8f7c5SWolfram Sang EXPORT_SYMBOL_GPL(i2c_acpi_find_bus_speed); 40053f8f7c5SWolfram Sang 401418e3ea1SSuzuki K Poulose static int i2c_acpi_find_match_adapter(struct device *dev, const void *data) 40253f8f7c5SWolfram Sang { 40353f8f7c5SWolfram Sang struct i2c_adapter *adapter = i2c_verify_adapter(dev); 40453f8f7c5SWolfram Sang 40553f8f7c5SWolfram Sang if (!adapter) 40653f8f7c5SWolfram Sang return 0; 40753f8f7c5SWolfram Sang 40853f8f7c5SWolfram Sang return ACPI_HANDLE(dev) == (acpi_handle)data; 40953f8f7c5SWolfram Sang } 41053f8f7c5SWolfram Sang 4111e91a2e5SRuslan Babayev struct i2c_adapter *i2c_acpi_find_adapter_by_handle(acpi_handle handle) 41253f8f7c5SWolfram Sang { 413644bf600SSuzuki K Poulose struct device *dev; 414644bf600SSuzuki K Poulose 415644bf600SSuzuki K Poulose dev = bus_find_device(&i2c_bus_type, NULL, handle, 416644bf600SSuzuki K Poulose i2c_acpi_find_match_adapter); 41753f8f7c5SWolfram Sang 41853f8f7c5SWolfram Sang return dev ? i2c_verify_adapter(dev) : NULL; 41953f8f7c5SWolfram Sang } 4201e91a2e5SRuslan Babayev EXPORT_SYMBOL_GPL(i2c_acpi_find_adapter_by_handle); 42153f8f7c5SWolfram Sang 42253f8f7c5SWolfram Sang static struct i2c_client *i2c_acpi_find_client_by_adev(struct acpi_device *adev) 42353f8f7c5SWolfram Sang { 42453f8f7c5SWolfram Sang struct device *dev; 4258daee952SWolfram Sang struct i2c_client *client; 42653f8f7c5SWolfram Sang 42700500147SSuzuki K Poulose dev = bus_find_device_by_acpi_dev(&i2c_bus_type, adev); 4288daee952SWolfram Sang if (!dev) 4298daee952SWolfram Sang return NULL; 4308daee952SWolfram Sang 4318daee952SWolfram Sang client = i2c_verify_client(dev); 4328daee952SWolfram Sang if (!client) 4338daee952SWolfram Sang put_device(dev); 4348daee952SWolfram Sang 4358daee952SWolfram Sang return client; 43653f8f7c5SWolfram Sang } 43753f8f7c5SWolfram Sang 43853f8f7c5SWolfram Sang static int i2c_acpi_notify(struct notifier_block *nb, unsigned long value, 43953f8f7c5SWolfram Sang void *arg) 44053f8f7c5SWolfram Sang { 44153f8f7c5SWolfram Sang struct acpi_device *adev = arg; 44253f8f7c5SWolfram Sang struct i2c_board_info info; 44353f8f7c5SWolfram Sang acpi_handle adapter_handle; 44453f8f7c5SWolfram Sang struct i2c_adapter *adapter; 44553f8f7c5SWolfram Sang struct i2c_client *client; 44653f8f7c5SWolfram Sang 44753f8f7c5SWolfram Sang switch (value) { 44853f8f7c5SWolfram Sang case ACPI_RECONFIG_DEVICE_ADD: 44953f8f7c5SWolfram Sang if (i2c_acpi_get_info(adev, &info, NULL, &adapter_handle)) 45053f8f7c5SWolfram Sang break; 45153f8f7c5SWolfram Sang 45253f8f7c5SWolfram Sang adapter = i2c_acpi_find_adapter_by_handle(adapter_handle); 45353f8f7c5SWolfram Sang if (!adapter) 45453f8f7c5SWolfram Sang break; 45553f8f7c5SWolfram Sang 45653f8f7c5SWolfram Sang i2c_acpi_register_device(adapter, adev, &info); 4576558b646SJamie Iles put_device(&adapter->dev); 45853f8f7c5SWolfram Sang break; 45953f8f7c5SWolfram Sang case ACPI_RECONFIG_DEVICE_REMOVE: 46053f8f7c5SWolfram Sang if (!acpi_device_enumerated(adev)) 46153f8f7c5SWolfram Sang break; 46253f8f7c5SWolfram Sang 46353f8f7c5SWolfram Sang client = i2c_acpi_find_client_by_adev(adev); 46453f8f7c5SWolfram Sang if (!client) 46553f8f7c5SWolfram Sang break; 46653f8f7c5SWolfram Sang 46753f8f7c5SWolfram Sang i2c_unregister_device(client); 46853f8f7c5SWolfram Sang put_device(&client->dev); 46953f8f7c5SWolfram Sang break; 47053f8f7c5SWolfram Sang } 47153f8f7c5SWolfram Sang 47253f8f7c5SWolfram Sang return NOTIFY_OK; 47353f8f7c5SWolfram Sang } 47453f8f7c5SWolfram Sang 47553f8f7c5SWolfram Sang struct notifier_block i2c_acpi_notifier = { 47653f8f7c5SWolfram Sang .notifier_call = i2c_acpi_notify, 47753f8f7c5SWolfram Sang }; 47853f8f7c5SWolfram Sang 47953f8f7c5SWolfram Sang /** 48053f8f7c5SWolfram Sang * i2c_acpi_new_device - Create i2c-client for the Nth I2cSerialBus resource 48153f8f7c5SWolfram Sang * @dev: Device owning the ACPI resources to get the client from 48253f8f7c5SWolfram Sang * @index: Index of ACPI resource to get 48353f8f7c5SWolfram Sang * @info: describes the I2C device; note this is modified (addr gets set) 48453f8f7c5SWolfram Sang * Context: can sleep 48553f8f7c5SWolfram Sang * 48653f8f7c5SWolfram Sang * By default the i2c subsys creates an i2c-client for the first I2cSerialBus 48753f8f7c5SWolfram Sang * resource of an acpi_device, but some acpi_devices have multiple I2cSerialBus 48853f8f7c5SWolfram Sang * resources, in that case this function can be used to create an i2c-client 48953f8f7c5SWolfram Sang * for other I2cSerialBus resources in the Current Resource Settings table. 49053f8f7c5SWolfram Sang * 49190a3be9bSWolfram Sang * Also see i2c_new_client_device, which this function calls to create the 49290a3be9bSWolfram Sang * i2c-client. 49353f8f7c5SWolfram Sang * 4942dea645fSAndy Shevchenko * Returns a pointer to the new i2c-client, or error pointer in case of failure. 4952dea645fSAndy Shevchenko * Specifically, -EPROBE_DEFER is returned if the adapter is not found. 49653f8f7c5SWolfram Sang */ 49753f8f7c5SWolfram Sang struct i2c_client *i2c_acpi_new_device(struct device *dev, int index, 49853f8f7c5SWolfram Sang struct i2c_board_info *info) 49953f8f7c5SWolfram Sang { 5003e34b513SAndy Shevchenko struct acpi_device *adev = ACPI_COMPANION(dev); 50153f8f7c5SWolfram Sang struct i2c_acpi_lookup lookup; 50253f8f7c5SWolfram Sang struct i2c_adapter *adapter; 50353f8f7c5SWolfram Sang LIST_HEAD(resource_list); 50453f8f7c5SWolfram Sang int ret; 50553f8f7c5SWolfram Sang 50653f8f7c5SWolfram Sang memset(&lookup, 0, sizeof(lookup)); 50753f8f7c5SWolfram Sang lookup.info = info; 50853f8f7c5SWolfram Sang lookup.device_handle = acpi_device_handle(adev); 50953f8f7c5SWolfram Sang lookup.index = index; 51053f8f7c5SWolfram Sang 51153f8f7c5SWolfram Sang ret = acpi_dev_get_resources(adev, &resource_list, 51253f8f7c5SWolfram Sang i2c_acpi_fill_info, &lookup); 5132dea645fSAndy Shevchenko if (ret < 0) 5142dea645fSAndy Shevchenko return ERR_PTR(ret); 5152dea645fSAndy Shevchenko 51653f8f7c5SWolfram Sang acpi_dev_free_resource_list(&resource_list); 51753f8f7c5SWolfram Sang 5182dea645fSAndy Shevchenko if (!info->addr) 5192dea645fSAndy Shevchenko return ERR_PTR(-EADDRNOTAVAIL); 52053f8f7c5SWolfram Sang 52153f8f7c5SWolfram Sang adapter = i2c_acpi_find_adapter_by_handle(lookup.adapter_handle); 52253f8f7c5SWolfram Sang if (!adapter) 5232dea645fSAndy Shevchenko return ERR_PTR(-EPROBE_DEFER); 52453f8f7c5SWolfram Sang 52590a3be9bSWolfram Sang return i2c_new_client_device(adapter, info); 52653f8f7c5SWolfram Sang } 52753f8f7c5SWolfram Sang EXPORT_SYMBOL_GPL(i2c_acpi_new_device); 52853f8f7c5SWolfram Sang 529*b18c1ad6SSakari Ailus bool i2c_acpi_waive_d0_probe(struct device *dev) 530*b18c1ad6SSakari Ailus { 531*b18c1ad6SSakari Ailus struct i2c_driver *driver = to_i2c_driver(dev->driver); 532*b18c1ad6SSakari Ailus struct acpi_device *adev = ACPI_COMPANION(dev); 533*b18c1ad6SSakari Ailus 534*b18c1ad6SSakari Ailus return driver->flags & I2C_DRV_ACPI_WAIVE_D0_PROBE && 535*b18c1ad6SSakari Ailus adev && adev->power.state_for_enumeration >= adev->power.state; 536*b18c1ad6SSakari Ailus } 537*b18c1ad6SSakari Ailus EXPORT_SYMBOL_GPL(i2c_acpi_waive_d0_probe); 538*b18c1ad6SSakari Ailus 53953f8f7c5SWolfram Sang #ifdef CONFIG_ACPI_I2C_OPREGION 54053f8f7c5SWolfram Sang static int acpi_gsb_i2c_read_bytes(struct i2c_client *client, 54153f8f7c5SWolfram Sang u8 cmd, u8 *data, u8 data_len) 54253f8f7c5SWolfram Sang { 54353f8f7c5SWolfram Sang 54453f8f7c5SWolfram Sang struct i2c_msg msgs[2]; 54553f8f7c5SWolfram Sang int ret; 54653f8f7c5SWolfram Sang u8 *buffer; 54753f8f7c5SWolfram Sang 54853f8f7c5SWolfram Sang buffer = kzalloc(data_len, GFP_KERNEL); 54953f8f7c5SWolfram Sang if (!buffer) 55053f8f7c5SWolfram Sang return AE_NO_MEMORY; 55153f8f7c5SWolfram Sang 55253f8f7c5SWolfram Sang msgs[0].addr = client->addr; 55353f8f7c5SWolfram Sang msgs[0].flags = client->flags; 55453f8f7c5SWolfram Sang msgs[0].len = 1; 55553f8f7c5SWolfram Sang msgs[0].buf = &cmd; 55653f8f7c5SWolfram Sang 55753f8f7c5SWolfram Sang msgs[1].addr = client->addr; 55853f8f7c5SWolfram Sang msgs[1].flags = client->flags | I2C_M_RD; 55953f8f7c5SWolfram Sang msgs[1].len = data_len; 56053f8f7c5SWolfram Sang msgs[1].buf = buffer; 56153f8f7c5SWolfram Sang 56253f8f7c5SWolfram Sang ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); 5637781edaeSHans de Goede if (ret < 0) { 5647781edaeSHans de Goede /* Getting a NACK is unfortunately normal with some DSTDs */ 5657781edaeSHans de Goede if (ret == -EREMOTEIO) 5667781edaeSHans de Goede dev_dbg(&client->adapter->dev, "i2c read %d bytes from client@%#x starting at reg %#x failed, error: %d\n", 567c8016fa2SHans de Goede data_len, client->addr, cmd, ret); 56853f8f7c5SWolfram Sang else 5697781edaeSHans de Goede dev_err(&client->adapter->dev, "i2c read %d bytes from client@%#x starting at reg %#x failed, error: %d\n", 5707781edaeSHans de Goede data_len, client->addr, cmd, ret); 5710a30446cSHans de Goede /* 2 transfers must have completed successfully */ 5720a30446cSHans de Goede } else if (ret == 2) { 57353f8f7c5SWolfram Sang memcpy(data, buffer, data_len); 5740a30446cSHans de Goede ret = 0; 5750a30446cSHans de Goede } else { 5760a30446cSHans de Goede ret = -EIO; 5777781edaeSHans de Goede } 57853f8f7c5SWolfram Sang 57953f8f7c5SWolfram Sang kfree(buffer); 58053f8f7c5SWolfram Sang return ret; 58153f8f7c5SWolfram Sang } 58253f8f7c5SWolfram Sang 58353f8f7c5SWolfram Sang static int acpi_gsb_i2c_write_bytes(struct i2c_client *client, 58453f8f7c5SWolfram Sang u8 cmd, u8 *data, u8 data_len) 58553f8f7c5SWolfram Sang { 58653f8f7c5SWolfram Sang 58753f8f7c5SWolfram Sang struct i2c_msg msgs[1]; 58853f8f7c5SWolfram Sang u8 *buffer; 58953f8f7c5SWolfram Sang int ret = AE_OK; 59053f8f7c5SWolfram Sang 59153f8f7c5SWolfram Sang buffer = kzalloc(data_len + 1, GFP_KERNEL); 59253f8f7c5SWolfram Sang if (!buffer) 59353f8f7c5SWolfram Sang return AE_NO_MEMORY; 59453f8f7c5SWolfram Sang 59553f8f7c5SWolfram Sang buffer[0] = cmd; 59653f8f7c5SWolfram Sang memcpy(buffer + 1, data, data_len); 59753f8f7c5SWolfram Sang 59853f8f7c5SWolfram Sang msgs[0].addr = client->addr; 59953f8f7c5SWolfram Sang msgs[0].flags = client->flags; 60053f8f7c5SWolfram Sang msgs[0].len = data_len + 1; 60153f8f7c5SWolfram Sang msgs[0].buf = buffer; 60253f8f7c5SWolfram Sang 60353f8f7c5SWolfram Sang ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); 60453f8f7c5SWolfram Sang 60553f8f7c5SWolfram Sang kfree(buffer); 606c463a158SHans de Goede 607c463a158SHans de Goede if (ret < 0) { 608c463a158SHans de Goede dev_err(&client->adapter->dev, "i2c write failed: %d\n", ret); 60953f8f7c5SWolfram Sang return ret; 61053f8f7c5SWolfram Sang } 61153f8f7c5SWolfram Sang 612c463a158SHans de Goede /* 1 transfer must have completed successfully */ 613c463a158SHans de Goede return (ret == 1) ? 0 : -EIO; 614c463a158SHans de Goede } 615c463a158SHans de Goede 61653f8f7c5SWolfram Sang static acpi_status 61753f8f7c5SWolfram Sang i2c_acpi_space_handler(u32 function, acpi_physical_address command, 61853f8f7c5SWolfram Sang u32 bits, u64 *value64, 61953f8f7c5SWolfram Sang void *handler_context, void *region_context) 62053f8f7c5SWolfram Sang { 62153f8f7c5SWolfram Sang struct gsb_buffer *gsb = (struct gsb_buffer *)value64; 62253f8f7c5SWolfram Sang struct i2c_acpi_handler_data *data = handler_context; 62353f8f7c5SWolfram Sang struct acpi_connection_info *info = &data->info; 62453f8f7c5SWolfram Sang struct acpi_resource_i2c_serialbus *sb; 62553f8f7c5SWolfram Sang struct i2c_adapter *adapter = data->adapter; 62653f8f7c5SWolfram Sang struct i2c_client *client; 62753f8f7c5SWolfram Sang struct acpi_resource *ares; 62853f8f7c5SWolfram Sang u32 accessor_type = function >> 16; 62953f8f7c5SWolfram Sang u8 action = function & ACPI_IO_MASK; 63053f8f7c5SWolfram Sang acpi_status ret; 63153f8f7c5SWolfram Sang int status; 63253f8f7c5SWolfram Sang 63353f8f7c5SWolfram Sang ret = acpi_buffer_to_resource(info->connection, info->length, &ares); 63453f8f7c5SWolfram Sang if (ACPI_FAILURE(ret)) 63553f8f7c5SWolfram Sang return ret; 63653f8f7c5SWolfram Sang 63753f8f7c5SWolfram Sang client = kzalloc(sizeof(*client), GFP_KERNEL); 63853f8f7c5SWolfram Sang if (!client) { 63953f8f7c5SWolfram Sang ret = AE_NO_MEMORY; 64053f8f7c5SWolfram Sang goto err; 64153f8f7c5SWolfram Sang } 64253f8f7c5SWolfram Sang 6430d5102feSAndy Shevchenko if (!value64 || !i2c_acpi_get_i2c_resource(ares, &sb)) { 64453f8f7c5SWolfram Sang ret = AE_BAD_PARAMETER; 64553f8f7c5SWolfram Sang goto err; 64653f8f7c5SWolfram Sang } 64753f8f7c5SWolfram Sang 64853f8f7c5SWolfram Sang client->adapter = adapter; 64953f8f7c5SWolfram Sang client->addr = sb->slave_address; 65053f8f7c5SWolfram Sang 65153f8f7c5SWolfram Sang if (sb->access_mode == ACPI_I2C_10BIT_MODE) 65253f8f7c5SWolfram Sang client->flags |= I2C_CLIENT_TEN; 65353f8f7c5SWolfram Sang 65453f8f7c5SWolfram Sang switch (accessor_type) { 65553f8f7c5SWolfram Sang case ACPI_GSB_ACCESS_ATTRIB_SEND_RCV: 65653f8f7c5SWolfram Sang if (action == ACPI_READ) { 65753f8f7c5SWolfram Sang status = i2c_smbus_read_byte(client); 65853f8f7c5SWolfram Sang if (status >= 0) { 65953f8f7c5SWolfram Sang gsb->bdata = status; 66053f8f7c5SWolfram Sang status = 0; 66153f8f7c5SWolfram Sang } 66253f8f7c5SWolfram Sang } else { 66353f8f7c5SWolfram Sang status = i2c_smbus_write_byte(client, gsb->bdata); 66453f8f7c5SWolfram Sang } 66553f8f7c5SWolfram Sang break; 66653f8f7c5SWolfram Sang 66753f8f7c5SWolfram Sang case ACPI_GSB_ACCESS_ATTRIB_BYTE: 66853f8f7c5SWolfram Sang if (action == ACPI_READ) { 66953f8f7c5SWolfram Sang status = i2c_smbus_read_byte_data(client, command); 67053f8f7c5SWolfram Sang if (status >= 0) { 67153f8f7c5SWolfram Sang gsb->bdata = status; 67253f8f7c5SWolfram Sang status = 0; 67353f8f7c5SWolfram Sang } 67453f8f7c5SWolfram Sang } else { 67553f8f7c5SWolfram Sang status = i2c_smbus_write_byte_data(client, command, 67653f8f7c5SWolfram Sang gsb->bdata); 67753f8f7c5SWolfram Sang } 67853f8f7c5SWolfram Sang break; 67953f8f7c5SWolfram Sang 68053f8f7c5SWolfram Sang case ACPI_GSB_ACCESS_ATTRIB_WORD: 68153f8f7c5SWolfram Sang if (action == ACPI_READ) { 68253f8f7c5SWolfram Sang status = i2c_smbus_read_word_data(client, command); 68353f8f7c5SWolfram Sang if (status >= 0) { 68453f8f7c5SWolfram Sang gsb->wdata = status; 68553f8f7c5SWolfram Sang status = 0; 68653f8f7c5SWolfram Sang } 68753f8f7c5SWolfram Sang } else { 68853f8f7c5SWolfram Sang status = i2c_smbus_write_word_data(client, command, 68953f8f7c5SWolfram Sang gsb->wdata); 69053f8f7c5SWolfram Sang } 69153f8f7c5SWolfram Sang break; 69253f8f7c5SWolfram Sang 69353f8f7c5SWolfram Sang case ACPI_GSB_ACCESS_ATTRIB_BLOCK: 69453f8f7c5SWolfram Sang if (action == ACPI_READ) { 69553f8f7c5SWolfram Sang status = i2c_smbus_read_block_data(client, command, 69653f8f7c5SWolfram Sang gsb->data); 69753f8f7c5SWolfram Sang if (status >= 0) { 69853f8f7c5SWolfram Sang gsb->len = status; 69953f8f7c5SWolfram Sang status = 0; 70053f8f7c5SWolfram Sang } 70153f8f7c5SWolfram Sang } else { 70253f8f7c5SWolfram Sang status = i2c_smbus_write_block_data(client, command, 70353f8f7c5SWolfram Sang gsb->len, gsb->data); 70453f8f7c5SWolfram Sang } 70553f8f7c5SWolfram Sang break; 70653f8f7c5SWolfram Sang 70753f8f7c5SWolfram Sang case ACPI_GSB_ACCESS_ATTRIB_MULTIBYTE: 70853f8f7c5SWolfram Sang if (action == ACPI_READ) { 70953f8f7c5SWolfram Sang status = acpi_gsb_i2c_read_bytes(client, command, 71053f8f7c5SWolfram Sang gsb->data, info->access_length); 71153f8f7c5SWolfram Sang } else { 71253f8f7c5SWolfram Sang status = acpi_gsb_i2c_write_bytes(client, command, 71353f8f7c5SWolfram Sang gsb->data, info->access_length); 71453f8f7c5SWolfram Sang } 71553f8f7c5SWolfram Sang break; 71653f8f7c5SWolfram Sang 71753f8f7c5SWolfram Sang default: 71853f8f7c5SWolfram Sang dev_warn(&adapter->dev, "protocol 0x%02x not supported for client 0x%02x\n", 71953f8f7c5SWolfram Sang accessor_type, client->addr); 72053f8f7c5SWolfram Sang ret = AE_BAD_PARAMETER; 72153f8f7c5SWolfram Sang goto err; 72253f8f7c5SWolfram Sang } 72353f8f7c5SWolfram Sang 72453f8f7c5SWolfram Sang gsb->status = status; 72553f8f7c5SWolfram Sang 72653f8f7c5SWolfram Sang err: 72753f8f7c5SWolfram Sang kfree(client); 72853f8f7c5SWolfram Sang ACPI_FREE(ares); 72953f8f7c5SWolfram Sang return ret; 73053f8f7c5SWolfram Sang } 73153f8f7c5SWolfram Sang 73253f8f7c5SWolfram Sang 73353f8f7c5SWolfram Sang int i2c_acpi_install_space_handler(struct i2c_adapter *adapter) 73453f8f7c5SWolfram Sang { 73553f8f7c5SWolfram Sang acpi_handle handle; 73653f8f7c5SWolfram Sang struct i2c_acpi_handler_data *data; 73753f8f7c5SWolfram Sang acpi_status status; 73853f8f7c5SWolfram Sang 73953f8f7c5SWolfram Sang if (!adapter->dev.parent) 74053f8f7c5SWolfram Sang return -ENODEV; 74153f8f7c5SWolfram Sang 74253f8f7c5SWolfram Sang handle = ACPI_HANDLE(adapter->dev.parent); 74353f8f7c5SWolfram Sang 74453f8f7c5SWolfram Sang if (!handle) 74553f8f7c5SWolfram Sang return -ENODEV; 74653f8f7c5SWolfram Sang 74753f8f7c5SWolfram Sang data = kzalloc(sizeof(struct i2c_acpi_handler_data), 74853f8f7c5SWolfram Sang GFP_KERNEL); 74953f8f7c5SWolfram Sang if (!data) 75053f8f7c5SWolfram Sang return -ENOMEM; 75153f8f7c5SWolfram Sang 75253f8f7c5SWolfram Sang data->adapter = adapter; 75353f8f7c5SWolfram Sang status = acpi_bus_attach_private_data(handle, (void *)data); 75453f8f7c5SWolfram Sang if (ACPI_FAILURE(status)) { 75553f8f7c5SWolfram Sang kfree(data); 75653f8f7c5SWolfram Sang return -ENOMEM; 75753f8f7c5SWolfram Sang } 75853f8f7c5SWolfram Sang 75953f8f7c5SWolfram Sang status = acpi_install_address_space_handler(handle, 76053f8f7c5SWolfram Sang ACPI_ADR_SPACE_GSBUS, 76153f8f7c5SWolfram Sang &i2c_acpi_space_handler, 76253f8f7c5SWolfram Sang NULL, 76353f8f7c5SWolfram Sang data); 76453f8f7c5SWolfram Sang if (ACPI_FAILURE(status)) { 76553f8f7c5SWolfram Sang dev_err(&adapter->dev, "Error installing i2c space handler\n"); 76653f8f7c5SWolfram Sang acpi_bus_detach_private_data(handle); 76753f8f7c5SWolfram Sang kfree(data); 76853f8f7c5SWolfram Sang return -ENOMEM; 76953f8f7c5SWolfram Sang } 77053f8f7c5SWolfram Sang 77153f8f7c5SWolfram Sang return 0; 77253f8f7c5SWolfram Sang } 77353f8f7c5SWolfram Sang 77453f8f7c5SWolfram Sang void i2c_acpi_remove_space_handler(struct i2c_adapter *adapter) 77553f8f7c5SWolfram Sang { 77653f8f7c5SWolfram Sang acpi_handle handle; 77753f8f7c5SWolfram Sang struct i2c_acpi_handler_data *data; 77853f8f7c5SWolfram Sang acpi_status status; 77953f8f7c5SWolfram Sang 78053f8f7c5SWolfram Sang if (!adapter->dev.parent) 78153f8f7c5SWolfram Sang return; 78253f8f7c5SWolfram Sang 78353f8f7c5SWolfram Sang handle = ACPI_HANDLE(adapter->dev.parent); 78453f8f7c5SWolfram Sang 78553f8f7c5SWolfram Sang if (!handle) 78653f8f7c5SWolfram Sang return; 78753f8f7c5SWolfram Sang 78853f8f7c5SWolfram Sang acpi_remove_address_space_handler(handle, 78953f8f7c5SWolfram Sang ACPI_ADR_SPACE_GSBUS, 79053f8f7c5SWolfram Sang &i2c_acpi_space_handler); 79153f8f7c5SWolfram Sang 79253f8f7c5SWolfram Sang status = acpi_bus_get_private_data(handle, (void **)&data); 79353f8f7c5SWolfram Sang if (ACPI_SUCCESS(status)) 79453f8f7c5SWolfram Sang kfree(data); 79553f8f7c5SWolfram Sang 79653f8f7c5SWolfram Sang acpi_bus_detach_private_data(handle); 79753f8f7c5SWolfram Sang } 79853f8f7c5SWolfram Sang #endif /* CONFIG_ACPI_I2C_OPREGION */ 799