Merge branch 'i2c/alert-for-acpi' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux

Pull i2c material for 5.18 that is depended on by subsequent device
properties changes.

* 'i2c/alert-for-acpi' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux:
  i2c: smbus: Use device_*() functions instead of of_*()
  docs: firmware-guide: ACPI: Add named interrupt doc
  device property: Add fwnode_irq_get_byname
This commit is contained in:
Rafael J. Wysocki 2022-02-14 18:55:50 +01:00
commit a47381055b
7 changed files with 82 additions and 11 deletions

View file

@ -143,6 +143,45 @@ In robust cases the client unfortunately needs to call
acpi_dma_request_slave_chan_by_index() directly and therefore choose the
specific FixedDMA resource by its index.
Named Interrupts
================
Drivers enumerated via ACPI can have names to interrupts in the ACPI table
which can be used to get the IRQ number in the driver.
The interrupt name can be listed in _DSD as 'interrupt-names'. The names
should be listed as an array of strings which will map to the Interrupt()
resource in the ACPI table corresponding to its index.
The table below shows an example of its usage::
Device (DEV0) {
...
Name (_CRS, ResourceTemplate() {
...
Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) {
0x20,
0x24
}
})
Name (_DSD, Package () {
ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
Package () {
Package () {"interrupt-names",
Package (2) {"default", "alert"}},
}
...
})
}
The interrupt name 'default' will correspond to 0x20 in Interrupt()
resource and 'alert' to 0x24. Note that only the Interrupt() resource
is mapped and not GpioInt() or similar.
The driver can call the function - fwnode_irq_get_byname() with the fwnode
and interrupt name as arguments to get the corresponding IRQ number.
SPI serial bus support
======================

View file

@ -935,6 +935,35 @@ void __iomem *fwnode_iomap(struct fwnode_handle *fwnode, int index)
}
EXPORT_SYMBOL(fwnode_iomap);
/**
* fwnode_irq_get_byname - Get IRQ from a fwnode using its name
* @fwnode: Pointer to the firmware node
* @name: IRQ name
*
* Description:
* Find a match to the string @name in the 'interrupt-names' string array
* in _DSD for ACPI, or of_node for Device Tree. Then get the Linux IRQ
* number of the IRQ resource corresponding to the index of the matched
* string.
*
* Return:
* Linux IRQ number on success, or negative errno otherwise.
*/
int fwnode_irq_get_byname(const struct fwnode_handle *fwnode, const char *name)
{
int index;
if (!name)
return -EINVAL;
index = fwnode_property_match_string(fwnode, "interrupt-names", name);
if (index < 0)
return index;
return fwnode_irq_get(fwnode, index);
}
EXPORT_SYMBOL(fwnode_irq_get_byname);
/**
* fwnode_graph_get_next_endpoint - Get next endpoint firmware node
* @fwnode: Pointer to the parent firmware node

View file

@ -1479,7 +1479,7 @@ static int i2c_register_adapter(struct i2c_adapter *adap)
goto out_list;
}
res = of_i2c_setup_smbus_alert(adap);
res = i2c_setup_smbus_alert(adap);
if (res)
goto out_reg;

View file

@ -14,6 +14,7 @@
#include <linux/err.h>
#include <linux/i2c.h>
#include <linux/i2c-smbus.h>
#include <linux/property.h>
#include <linux/slab.h>
#include "i2c-core.h"
@ -701,13 +702,13 @@ struct i2c_client *i2c_new_smbus_alert_device(struct i2c_adapter *adapter,
}
EXPORT_SYMBOL_GPL(i2c_new_smbus_alert_device);
#if IS_ENABLED(CONFIG_I2C_SMBUS) && IS_ENABLED(CONFIG_OF)
int of_i2c_setup_smbus_alert(struct i2c_adapter *adapter)
#if IS_ENABLED(CONFIG_I2C_SMBUS)
int i2c_setup_smbus_alert(struct i2c_adapter *adapter)
{
int irq;
irq = of_property_match_string(adapter->dev.of_node, "interrupt-names",
"smbus_alert");
irq = device_property_match_string(adapter->dev.parent, "interrupt-names",
"smbus_alert");
if (irq == -EINVAL || irq == -ENODATA)
return 0;
else if (irq < 0)
@ -715,5 +716,5 @@ int of_i2c_setup_smbus_alert(struct i2c_adapter *adapter)
return PTR_ERR_OR_ZERO(i2c_new_smbus_alert_device(adapter, NULL));
}
EXPORT_SYMBOL_GPL(of_i2c_setup_smbus_alert);
EXPORT_SYMBOL_GPL(i2c_setup_smbus_alert);
#endif

View file

@ -13,7 +13,7 @@
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of_irq.h>
#include <linux/property.h>
#include <linux/slab.h>
#include <linux/workqueue.h>
@ -128,7 +128,8 @@ static int smbalert_probe(struct i2c_client *ara,
if (setup) {
irq = setup->irq;
} else {
irq = of_irq_get_byname(adapter->dev.of_node, "smbus_alert");
irq = fwnode_irq_get_byname(dev_fwnode(adapter->dev.parent),
"smbus_alert");
if (irq <= 0)
return irq;
}

View file

@ -30,10 +30,10 @@ struct i2c_client *i2c_new_smbus_alert_device(struct i2c_adapter *adapter,
struct i2c_smbus_alert_setup *setup);
int i2c_handle_smbus_alert(struct i2c_client *ara);
#if IS_ENABLED(CONFIG_I2C_SMBUS) && IS_ENABLED(CONFIG_OF)
int of_i2c_setup_smbus_alert(struct i2c_adapter *adap);
#if IS_ENABLED(CONFIG_I2C_SMBUS)
int i2c_setup_smbus_alert(struct i2c_adapter *adap);
#else
static inline int of_i2c_setup_smbus_alert(struct i2c_adapter *adap)
static inline int i2c_setup_smbus_alert(struct i2c_adapter *adap)
{
return 0;
}

View file

@ -121,6 +121,7 @@ struct fwnode_handle *fwnode_handle_get(struct fwnode_handle *fwnode);
void fwnode_handle_put(struct fwnode_handle *fwnode);
int fwnode_irq_get(const struct fwnode_handle *fwnode, unsigned int index);
int fwnode_irq_get_byname(const struct fwnode_handle *fwnode, const char *name);
void __iomem *fwnode_iomap(struct fwnode_handle *fwnode, int index);