From a5969cabbb4660eab42b6ef0412cbbd1200cf14d Mon Sep 17 00:00:00 2001 From: hc <hc@nodka.com> Date: Sat, 12 Oct 2024 07:10:09 +0000 Subject: [PATCH] 修改led为gpio --- kernel/drivers/i2c/i2c-core-acpi.c | 164 +++++++++++++++++++++++++++++++----------------------- 1 files changed, 95 insertions(+), 69 deletions(-) diff --git a/kernel/drivers/i2c/i2c-core-acpi.c b/kernel/drivers/i2c/i2c-core-acpi.c index 8288cfb..4b136d8 100644 --- a/kernel/drivers/i2c/i2c-core-acpi.c +++ b/kernel/drivers/i2c/i2c-core-acpi.c @@ -1,12 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * Linux I2C core ACPI support code * * Copyright (C) 2014 Intel Corp, Author: Lan Tianyu <tianyu.lan@intel.com> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. */ #include <linux/acpi.h> @@ -46,6 +42,33 @@ u32 force_speed; }; +/** + * i2c_acpi_get_i2c_resource - Gets I2cSerialBus resource if type matches + * @ares: ACPI resource + * @i2c: Pointer to I2cSerialBus resource will be returned here + * + * Checks if the given ACPI resource is of type I2cSerialBus. + * In this case, returns a pointer to it to the caller. + * + * Returns true if resource type is of I2cSerialBus, otherwise false. + */ +bool i2c_acpi_get_i2c_resource(struct acpi_resource *ares, + struct acpi_resource_i2c_serialbus **i2c) +{ + struct acpi_resource_i2c_serialbus *sb; + + if (ares->type != ACPI_RESOURCE_TYPE_SERIAL_BUS) + return false; + + sb = &ares->data.i2c_serial_bus; + if (sb->type != ACPI_RESOURCE_SERIAL_TYPE_I2C) + return false; + + *i2c = sb; + return true; +} +EXPORT_SYMBOL_GPL(i2c_acpi_get_i2c_resource); + static int i2c_acpi_fill_info(struct acpi_resource *ares, void *data) { struct i2c_acpi_lookup *lookup = data; @@ -53,11 +76,7 @@ struct acpi_resource_i2c_serialbus *sb; acpi_status status; - if (info->addr || ares->type != ACPI_RESOURCE_TYPE_SERIAL_BUS) - return 1; - - sb = &ares->data.i2c_serial_bus; - if (sb->type != ACPI_RESOURCE_SERIAL_TYPE_I2C) + if (info->addr || !i2c_acpi_get_i2c_resource(ares, &sb)) return 1; if (lookup->index != -1 && lookup->n++ != lookup->index) @@ -66,7 +85,7 @@ status = acpi_get_handle(lookup->device_handle, sb->resource_source.string_ptr, &lookup->adapter_handle); - if (!ACPI_SUCCESS(status)) + if (ACPI_FAILURE(status)) return 1; info->addr = sb->slave_address; @@ -93,8 +112,7 @@ struct list_head resource_list; int ret; - if (acpi_bus_get_status(adev) || !adev->status.present || - acpi_device_enumerated(adev)) + if (acpi_bus_get_status(adev) || !adev->status.present) return -EINVAL; if (acpi_match_device_ids(adev, i2c_acpi_ignored_device_ids) == 0) @@ -115,19 +133,61 @@ return 0; } +static int i2c_acpi_add_resource(struct acpi_resource *ares, void *data) +{ + int *irq = data; + struct resource r; + + if (*irq <= 0 && acpi_dev_resource_interrupt(ares, 0, &r)) + *irq = i2c_dev_irq_from_resources(&r, 1); + + return 1; /* No need to add resource to the list */ +} + +/** + * i2c_acpi_get_irq - get device IRQ number from ACPI + * @client: Pointer to the I2C client device + * + * Find the IRQ number used by a specific client device. + * + * Return: The IRQ number or an error code. + */ +int i2c_acpi_get_irq(struct i2c_client *client) +{ + struct acpi_device *adev = ACPI_COMPANION(&client->dev); + struct list_head resource_list; + int irq = -ENOENT; + int ret; + + INIT_LIST_HEAD(&resource_list); + + ret = acpi_dev_get_resources(adev, &resource_list, + i2c_acpi_add_resource, &irq); + if (ret < 0) + return ret; + + acpi_dev_free_resource_list(&resource_list); + + if (irq == -ENOENT) + irq = acpi_dev_gpio_irq_get(adev, 0); + + return irq; +} + static int i2c_acpi_get_info(struct acpi_device *adev, struct i2c_board_info *info, struct i2c_adapter *adapter, acpi_handle *adapter_handle) { - struct list_head resource_list; - struct resource_entry *entry; struct i2c_acpi_lookup lookup; int ret; memset(&lookup, 0, sizeof(lookup)); lookup.info = info; lookup.index = -1; + + if (acpi_device_enumerated(adev)) + return -EINVAL; ret = i2c_acpi_do_lookup(adev, &lookup); if (ret) @@ -152,21 +212,6 @@ if (adapter_handle) *adapter_handle = lookup.adapter_handle; - /* Then fill IRQ number if any */ - INIT_LIST_HEAD(&resource_list); - ret = acpi_dev_get_resources(adev, &resource_list, NULL, NULL); - if (ret < 0) - return -EINVAL; - - resource_list_for_each_entry(entry, &resource_list) { - if (resource_type(entry->res) == IORESOURCE_IRQ) { - info->irq = entry->res->start; - break; - } - } - - acpi_dev_free_resource_list(&resource_list); - acpi_set_modalias(adev, dev_name(&adev->dev), info->type, sizeof(info->type)); @@ -180,7 +225,7 @@ adev->power.flags.ignore_parent = true; acpi_device_set_enumerated(adev); - if (!i2c_new_device(adapter, info)) { + if (IS_ERR(i2c_new_client_device(adapter, info))) { adev->power.flags.ignore_parent = false; dev_err(&adapter->dev, "failed to add I2C device %s from ACPI\n", @@ -241,16 +286,6 @@ acpi_walk_dep_device_list(handle); } -const struct acpi_device_id * -i2c_acpi_match_device(const struct acpi_device_id *matches, - struct i2c_client *client) -{ - if (!(client && matches)) - return NULL; - - return acpi_match_device(matches, &client->dev); -} - static const struct acpi_device_id i2c_acpi_force_400khz_device_ids[] = { /* * These Silead touchscreen controllers only work at 400KHz, for @@ -283,7 +318,7 @@ lookup->min_speed = lookup->speed; if (acpi_match_device_ids(adev, i2c_acpi_force_400khz_device_ids) == 0) - lookup->force_speed = 400000; + lookup->force_speed = I2C_MAX_FAST_MODE_FREQ; return AE_OK; } @@ -335,7 +370,7 @@ } EXPORT_SYMBOL_GPL(i2c_acpi_find_bus_speed); -static int i2c_acpi_find_match_adapter(struct device *dev, void *data) +static int i2c_acpi_find_match_adapter(struct device *dev, const void *data) { struct i2c_adapter *adapter = i2c_verify_adapter(dev); @@ -345,27 +380,23 @@ return ACPI_HANDLE(dev) == (acpi_handle)data; } -static int i2c_acpi_find_match_device(struct device *dev, void *data) -{ - return ACPI_COMPANION(dev) == data; -} - -static struct i2c_adapter *i2c_acpi_find_adapter_by_handle(acpi_handle handle) +struct i2c_adapter *i2c_acpi_find_adapter_by_handle(acpi_handle handle) { struct device *dev; dev = bus_find_device(&i2c_bus_type, NULL, handle, i2c_acpi_find_match_adapter); + return dev ? i2c_verify_adapter(dev) : NULL; } +EXPORT_SYMBOL_GPL(i2c_acpi_find_adapter_by_handle); static struct i2c_client *i2c_acpi_find_client_by_adev(struct acpi_device *adev) { struct device *dev; struct i2c_client *client; - dev = bus_find_device(&i2c_bus_type, NULL, adev, - i2c_acpi_find_match_device); + dev = bus_find_device_by_acpi_dev(&i2c_bus_type, adev); if (!dev) return NULL; @@ -429,22 +460,20 @@ * resources, in that case this function can be used to create an i2c-client * for other I2cSerialBus resources in the Current Resource Settings table. * - * Also see i2c_new_device, which this function calls to create the i2c-client. + * Also see i2c_new_client_device, which this function calls to create the + * i2c-client. * - * Returns a pointer to the new i2c-client, or NULL if the adapter is not found. + * Returns a pointer to the new i2c-client, or error pointer in case of failure. + * Specifically, -EPROBE_DEFER is returned if the adapter is not found. */ struct i2c_client *i2c_acpi_new_device(struct device *dev, int index, struct i2c_board_info *info) { + struct acpi_device *adev = ACPI_COMPANION(dev); struct i2c_acpi_lookup lookup; struct i2c_adapter *adapter; - struct acpi_device *adev; LIST_HEAD(resource_list); int ret; - - adev = ACPI_COMPANION(dev); - if (!adev) - return NULL; memset(&lookup, 0, sizeof(lookup)); lookup.info = info; @@ -453,16 +482,19 @@ ret = acpi_dev_get_resources(adev, &resource_list, i2c_acpi_fill_info, &lookup); + if (ret < 0) + return ERR_PTR(ret); + acpi_dev_free_resource_list(&resource_list); - if (ret < 0 || !info->addr) - return NULL; + if (!info->addr) + return ERR_PTR(-EADDRNOTAVAIL); adapter = i2c_acpi_find_adapter_by_handle(lookup.adapter_handle); if (!adapter) - return NULL; + return ERR_PTR(-EPROBE_DEFER); - return i2c_new_device(adapter, info); + return i2c_new_client_device(adapter, info); } EXPORT_SYMBOL_GPL(i2c_acpi_new_device); @@ -570,13 +602,7 @@ goto err; } - if (!value64 || ares->type != ACPI_RESOURCE_TYPE_SERIAL_BUS) { - ret = AE_BAD_PARAMETER; - goto err; - } - - sb = &ares->data.i2c_serial_bus; - if (sb->type != ACPI_RESOURCE_SERIAL_TYPE_I2C) { + if (!value64 || !i2c_acpi_get_i2c_resource(ares, &sb)) { ret = AE_BAD_PARAMETER; goto err; } -- Gitblit v1.6.2