On Tue, Dec 26, 2023 at 12:21:06PM -0700, Mark Hasemeyer wrote:
> Other information besides wake capability can be provided about GPIO
> IRQs such as triggering, polarity, and sharability. Use resource flags
> to provide this information to the caller if they want it.
>
> This should keep the API more robust over time as flags are added,
> modified, or removed. It also more closely matches acpi_irq_get() which
> take a resource as an argument.
>
> Rename the function to acpi_dev_get_gpio_irq_resource() to better
> describe the function's new behavior.
...
> + res_flags = acpi_dev_irq_flags(info.triggering, info.polarity,
> + info.shareable, info.wake_capable);
Broken indentation of the second line.
...
> + *r = DEFINE_RES_NAMED(irq, 1, NULL, res_flags);
So? The whole exercise with the first patch is to have here:
*r = DEFINE_RES_IRQ_NAMED_FLAGS(irq, NULL, res_flags);
...
> + struct resource r;
I prefer to see
struct resource r = {};
even if it makes no difference. This allows to have robust code.
> + ret = acpi_dev_get_gpio_irq_resource(adev, name, index, &r);
> + return ret ?: r.start;
Btw, this function requires header to include ioport.h. I'm not sure
if it's good for ACPI. I would prefer safest approach, i.e. exporting
this from a C code, i.e. gpiolib-acpi.c.
>
> > + *r = DEFINE_RES_NAMED(irq, 1, NULL, res_flags);
>
> So? The whole exercise with the first patch is to have here:
>
> *r = DEFINE_RES_IRQ_NAMED_FLAGS(irq, NULL, res_flags);
Thanks. I was staring at the macro changes in ioport.h for too long...
>
> > + ret = acpi_dev_get_gpio_irq_resource(adev, name, index, &r);
> > + return ret ?: r.start;
>
> Btw, this function requires header to include ioport.h. I'm not sure
> if it's good for ACPI. I would prefer safest approach, i.e. exporting
> this from a C code, i.e. gpiolib-acpi.c.
It actually just needs 'struct resource' declared. I removed the
dependency on ioport.h, but it may make sense to leave the definition
of 'acpi_dev_gpio_irq_get_by()' here because non ACPI based systems
need a default implementation anyway.
@@ -99,6 +99,7 @@ struct acpi_gpio_chip {
* @pin_config: pin bias as provided by ACPI
* @polarity: interrupt polarity as provided by ACPI
* @triggering: triggering type as provided by ACPI
+ * @shareable: share type as provided by ACPI (shared vs exclusive).
* @wake_capable: wake capability as provided by ACPI
* @debounce: debounce timeout as provided by ACPI
* @quirks: Linux specific quirks as provided by struct acpi_gpio_mapping
@@ -111,6 +112,7 @@ struct acpi_gpio_info {
int polarity;
int triggering;
bool wake_capable;
+ bool shareable;
unsigned int debounce;
unsigned int quirks;
};
@@ -760,6 +762,7 @@ static int acpi_populate_gpio_lookup(struct acpi_resource *ares, void *data)
lookup->info.debounce = agpio->debounce_timeout;
lookup->info.gpioint = gpioint;
lookup->info.wake_capable = acpi_gpio_irq_is_wake(&lookup->info.adev->dev, agpio);
+ lookup->info.shareable = agpio->shareable == ACPI_SHARED;
/*
* Polarity and triggering are only specified for GpioInt
@@ -1004,11 +1007,11 @@ struct gpio_desc *acpi_find_gpio(struct fwnode_handle *fwnode,
}
/**
- * acpi_dev_gpio_irq_wake_get_by() - Find GpioInt and translate it to Linux IRQ number
+ * acpi_dev_get_gpio_irq_resource() - Find GpioInt and populate resource struct
* @adev: pointer to a ACPI device to get IRQ from
* @name: optional name of GpioInt resource
* @index: index of GpioInt resource (starting from %0)
- * @wake_capable: Set to true if the IRQ is wake capable
+ * @r: pointer to resource to populate with IRQ information.
*
* If the device has one or more GpioInt resources, this function can be
* used to translate from the GPIO offset in the resource to the Linux IRQ
@@ -1023,10 +1026,12 @@ struct gpio_desc *acpi_find_gpio(struct fwnode_handle *fwnode,
* The GPIO is considered wake capable if the GpioInt resource specifies
* SharedAndWake or ExclusiveAndWake.
*
- * Return: Linux IRQ number (> %0) on success, negative errno on failure.
+ * IRQ number will be available in the resource structure.
+ *
+ * Return: 0 on success, negative errno on failure.
*/
-int acpi_dev_gpio_irq_wake_get_by(struct acpi_device *adev, const char *name, int index,
- bool *wake_capable)
+int acpi_dev_get_gpio_irq_resource(struct acpi_device *adev, const char *name, int index,
+ struct resource *r)
{
int idx, i;
unsigned int irq_flags;
@@ -1045,6 +1050,7 @@ int acpi_dev_gpio_irq_wake_get_by(struct acpi_device *adev, const char *name, in
if (info.gpioint && idx++ == index) {
unsigned long lflags = GPIO_LOOKUP_FLAGS_DEFAULT;
enum gpiod_flags dflags = GPIOD_ASIS;
+ unsigned long res_flags;
char label[32];
int irq;
@@ -1084,16 +1090,19 @@ int acpi_dev_gpio_irq_wake_get_by(struct acpi_device *adev, const char *name, in
}
/* avoid suspend issues with GPIOs when systems are using S3 */
- if (wake_capable && acpi_gbl_FADT.flags & ACPI_FADT_LOW_POWER_S0)
- *wake_capable = info.wake_capable;
+ if (info.wake_capable && !(acpi_gbl_FADT.flags & ACPI_FADT_LOW_POWER_S0))
+ info.wake_capable = false;
- return irq;
+ res_flags = acpi_dev_irq_flags(info.triggering, info.polarity,
+ info.shareable, info.wake_capable);
+ *r = DEFINE_RES_NAMED(irq, 1, NULL, res_flags);
+ return 0;
}
}
return -ENOENT;
}
-EXPORT_SYMBOL_GPL(acpi_dev_gpio_irq_wake_get_by);
+EXPORT_SYMBOL_GPL(acpi_dev_get_gpio_irq_resource);
static acpi_status
acpi_gpio_adr_space_handler(u32 function, acpi_physical_address address,
@@ -203,6 +203,7 @@ int i2c_acpi_get_irq(struct i2c_client *client, bool *wake_capable)
{
struct acpi_device *adev = ACPI_COMPANION(&client->dev);
struct list_head resource_list;
+ struct resource irqres;
struct i2c_acpi_irq_context irq_ctx = {
.irq = -ENOENT,
};
@@ -217,8 +218,13 @@ int i2c_acpi_get_irq(struct i2c_client *client, bool *wake_capable)
acpi_dev_free_resource_list(&resource_list);
- if (irq_ctx.irq == -ENOENT)
- irq_ctx.irq = acpi_dev_gpio_irq_wake_get(adev, 0, &irq_ctx.wake_capable);
+ if (irq_ctx.irq == -ENOENT) {
+ ret = acpi_dev_get_gpio_irq_resource(adev, NULL, 0, &irqres);
+ if (ret)
+ return ret;
+ irq_ctx.irq = irqres.start;
+ irq_ctx.wake_capable = irqres.flags & IORESOURCE_IRQ_WAKECAPABLE;
+ }
if (irq_ctx.irq < 0)
return irq_ctx.irq;
@@ -1221,8 +1221,8 @@ bool acpi_gpio_get_irq_resource(struct acpi_resource *ares,
struct acpi_resource_gpio **agpio);
bool acpi_gpio_get_io_resource(struct acpi_resource *ares,
struct acpi_resource_gpio **agpio);
-int acpi_dev_gpio_irq_wake_get_by(struct acpi_device *adev, const char *name, int index,
- bool *wake_capable);
+int acpi_dev_get_gpio_irq_resource(struct acpi_device *adev, const char *name, int index,
+ struct resource *r);
#else
static inline bool acpi_gpio_get_irq_resource(struct acpi_resource *ares,
struct acpi_resource_gpio **agpio)
@@ -1234,28 +1234,25 @@ static inline bool acpi_gpio_get_io_resource(struct acpi_resource *ares,
{
return false;
}
-static inline int acpi_dev_gpio_irq_wake_get_by(struct acpi_device *adev, const char *name,
- int index, bool *wake_capable)
+static inline int acpi_dev_get_gpio_irq_resource(struct acpi_device *adev, const char *name,
+ int index, struct resource *r)
{
return -ENXIO;
}
#endif
-static inline int acpi_dev_gpio_irq_wake_get(struct acpi_device *adev, int index,
- bool *wake_capable)
+static inline int acpi_dev_gpio_irq_get_by(struct acpi_device *adev, const char *name, int index)
{
- return acpi_dev_gpio_irq_wake_get_by(adev, NULL, index, wake_capable);
-}
+ struct resource r;
+ int ret;
-static inline int acpi_dev_gpio_irq_get_by(struct acpi_device *adev, const char *name,
- int index)
-{
- return acpi_dev_gpio_irq_wake_get_by(adev, name, index, NULL);
+ ret = acpi_dev_get_gpio_irq_resource(adev, name, index, &r);
+ return ret ?: r.start;
}
static inline int acpi_dev_gpio_irq_get(struct acpi_device *adev, int index)
{
- return acpi_dev_gpio_irq_wake_get_by(adev, NULL, index, NULL);
+ return acpi_dev_gpio_irq_get_by(adev, NULL, index);
}
/* Device properties */