mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-21 08:19:28 +00:00
Merge branch 'i2c/for-INT33FE' into i2c/for-4.12
Pull in the immutable branch with I2C ACPI core extensions to support the INT33FE driver.
This commit is contained in:
commit
c99a30d8c4
2 changed files with 69 additions and 3 deletions
|
@ -112,6 +112,8 @@ struct i2c_acpi_lookup {
|
|||
acpi_handle adapter_handle;
|
||||
acpi_handle device_handle;
|
||||
acpi_handle search_handle;
|
||||
int n;
|
||||
int index;
|
||||
u32 speed;
|
||||
u32 min_speed;
|
||||
};
|
||||
|
@ -130,6 +132,9 @@ static int i2c_acpi_fill_info(struct acpi_resource *ares, void *data)
|
|||
if (sb->type != ACPI_RESOURCE_SERIAL_TYPE_I2C)
|
||||
return 1;
|
||||
|
||||
if (lookup->index != -1 && lookup->n++ != lookup->index)
|
||||
return 1;
|
||||
|
||||
status = acpi_get_handle(lookup->device_handle,
|
||||
sb->resource_source.string_ptr,
|
||||
&lookup->adapter_handle);
|
||||
|
@ -182,6 +187,7 @@ static int i2c_acpi_get_info(struct acpi_device *adev,
|
|||
|
||||
memset(&lookup, 0, sizeof(lookup));
|
||||
lookup.info = info;
|
||||
lookup.index = -1;
|
||||
|
||||
ret = i2c_acpi_do_lookup(adev, &lookup);
|
||||
if (ret)
|
||||
|
@ -328,6 +334,7 @@ u32 i2c_acpi_find_bus_speed(struct device *dev)
|
|||
lookup.search_handle = ACPI_HANDLE(dev);
|
||||
lookup.min_speed = UINT_MAX;
|
||||
lookup.info = &dummy;
|
||||
lookup.index = -1;
|
||||
|
||||
status = acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
|
||||
I2C_ACPI_MAX_SCAN_DEPTH,
|
||||
|
@ -414,6 +421,55 @@ static int i2c_acpi_notify(struct notifier_block *nb, unsigned long value,
|
|||
static struct notifier_block i2c_acpi_notifier = {
|
||||
.notifier_call = i2c_acpi_notify,
|
||||
};
|
||||
|
||||
/**
|
||||
* i2c_acpi_new_device - Create i2c-client for the Nth I2cSerialBus resource
|
||||
* @dev: Device owning the ACPI resources to get the client from
|
||||
* @index: Index of ACPI resource to get
|
||||
* @info: describes the I2C device; note this is modified (addr gets set)
|
||||
* Context: can sleep
|
||||
*
|
||||
* By default the i2c subsys creates an i2c-client for the first I2cSerialBus
|
||||
* resource of an acpi_device, but some acpi_devices have multiple I2cSerialBus
|
||||
* 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.
|
||||
*
|
||||
* Returns a pointer to the new i2c-client, or NULL if the adapter is not found.
|
||||
*/
|
||||
struct i2c_client *i2c_acpi_new_device(struct device *dev, int index,
|
||||
struct i2c_board_info *info)
|
||||
{
|
||||
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;
|
||||
lookup.device_handle = acpi_device_handle(adev);
|
||||
lookup.index = index;
|
||||
|
||||
ret = acpi_dev_get_resources(adev, &resource_list,
|
||||
i2c_acpi_fill_info, &lookup);
|
||||
acpi_dev_free_resource_list(&resource_list);
|
||||
|
||||
if (ret < 0 || !info->addr)
|
||||
return NULL;
|
||||
|
||||
adapter = i2c_acpi_find_adapter_by_handle(lookup.adapter_handle);
|
||||
if (!adapter)
|
||||
return NULL;
|
||||
|
||||
return i2c_new_device(adapter, info);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(i2c_acpi_new_device);
|
||||
#else /* CONFIG_ACPI */
|
||||
static inline void i2c_acpi_register_devices(struct i2c_adapter *adap) { }
|
||||
extern struct notifier_block i2c_acpi_notifier;
|
||||
|
@ -929,7 +985,9 @@ static int i2c_device_probe(struct device *dev)
|
|||
if (!client)
|
||||
return 0;
|
||||
|
||||
if (!client->irq) {
|
||||
driver = to_i2c_driver(dev->driver);
|
||||
|
||||
if (!client->irq && !driver->disable_i2c_core_irq_mapping) {
|
||||
int irq = -ENOENT;
|
||||
|
||||
if (client->flags & I2C_CLIENT_HOST_NOTIFY) {
|
||||
|
@ -951,8 +1009,6 @@ static int i2c_device_probe(struct device *dev)
|
|||
client->irq = irq;
|
||||
}
|
||||
|
||||
driver = to_i2c_driver(dev->driver);
|
||||
|
||||
/*
|
||||
* An I2C ID table is not mandatory, if and only if, a suitable Device
|
||||
* Tree match table entry is supplied for the probing device.
|
||||
|
|
|
@ -149,6 +149,7 @@ enum i2c_alert_protocol {
|
|||
* @detect: Callback for device detection
|
||||
* @address_list: The I2C addresses to probe (for detect)
|
||||
* @clients: List of detected clients we created (for i2c-core use only)
|
||||
* @disable_i2c_core_irq_mapping: Tell the i2c-core to not do irq-mapping
|
||||
*
|
||||
* The driver.owner field should be set to the module owner of this driver.
|
||||
* The driver.name field should be set to the name of this driver.
|
||||
|
@ -212,6 +213,8 @@ struct i2c_driver {
|
|||
int (*detect)(struct i2c_client *, struct i2c_board_info *);
|
||||
const unsigned short *address_list;
|
||||
struct list_head clients;
|
||||
|
||||
bool disable_i2c_core_irq_mapping;
|
||||
};
|
||||
#define to_i2c_driver(d) container_of(d, struct i2c_driver, driver)
|
||||
|
||||
|
@ -824,11 +827,18 @@ static inline const struct of_device_id
|
|||
|
||||
#if IS_ENABLED(CONFIG_ACPI)
|
||||
u32 i2c_acpi_find_bus_speed(struct device *dev);
|
||||
struct i2c_client *i2c_acpi_new_device(struct device *dev, int index,
|
||||
struct i2c_board_info *info);
|
||||
#else
|
||||
static inline u32 i2c_acpi_find_bus_speed(struct device *dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static inline struct i2c_client *i2c_acpi_new_device(struct device *dev,
|
||||
int index, struct i2c_board_info *info)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
#endif /* CONFIG_ACPI */
|
||||
|
||||
#endif /* _LINUX_I2C_H */
|
||||
|
|
Loading…
Reference in a new issue