]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
i2c: support gpio-binding for SMBAlerts
authorWolfram Sang <wsa+renesas@sang-engineering.com>
Mon, 9 Sep 2024 11:02:56 +0000 (13:02 +0200)
committerWolfram Sang <wsa+renesas@sang-engineering.com>
Tue, 8 Oct 2024 09:04:20 +0000 (11:04 +0200)
Most I2C controllers do not have a dedicated pin for SMBus Alerts. Allow
them to define a GPIO as a side-channel.

Signed-off-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
Reviewed-by: Andi Shyti <andi.shyti@kernel.org>
drivers/i2c/i2c-core-smbus.c
drivers/i2c/i2c-smbus.c

index e3b96fc53b5c258b5d2e210a0ea6d46c0ac8a430..0a6bdc6df1723cc1017abae5e4870072dabf7ea6 100644 (file)
@@ -712,12 +712,15 @@ int i2c_setup_smbus_alert(struct i2c_adapter *adapter)
        if (!parent)
                return 0;
 
+       /* Report serious errors */
        irq = device_property_match_string(parent, "interrupt-names", "smbus_alert");
-       if (irq == -EINVAL || irq == -ENODATA)
-               return 0;
-       else if (irq < 0)
+       if (irq < 0 && irq != -EINVAL && irq != -ENODATA)
                return irq;
 
+       /* Skip setup when no irq was found */
+       if (irq < 0 && !device_property_present(parent, "smbalert-gpios"))
+               return 0;
+
        return PTR_ERR_OR_ZERO(i2c_new_smbus_alert_device(adapter, NULL));
 }
 #endif
index 8256f7aed0cf860ae548a52899380d2df0edab5a..7d40e7aa37992842c266e685aa8b45b5a02c8064 100644 (file)
@@ -8,6 +8,7 @@
 
 #include <linux/device.h>
 #include <linux/dmi.h>
+#include <linux/gpio/consumer.h>
 #include <linux/i2c.h>
 #include <linux/i2c-smbus.h>
 #include <linux/interrupt.h>
@@ -167,6 +168,8 @@ static int smbalert_probe(struct i2c_client *ara)
        struct i2c_smbus_alert_setup *setup = dev_get_platdata(&ara->dev);
        struct i2c_smbus_alert *alert;
        struct i2c_adapter *adapter = ara->adapter;
+       unsigned long irqflags = IRQF_SHARED | IRQF_ONESHOT;
+       struct gpio_desc *gpiod;
        int res, irq;
 
        alert = devm_kzalloc(&ara->dev, sizeof(struct i2c_smbus_alert),
@@ -179,18 +182,25 @@ static int smbalert_probe(struct i2c_client *ara)
        } else {
                irq = fwnode_irq_get_byname(dev_fwnode(adapter->dev.parent),
                                            "smbus_alert");
-               if (irq <= 0)
-                       return irq;
+               if (irq <= 0) {
+                       gpiod = devm_gpiod_get(adapter->dev.parent, "smbalert", GPIOD_IN);
+                       if (IS_ERR(gpiod))
+                               return PTR_ERR(gpiod);
+
+                       irq = gpiod_to_irq(gpiod);
+                       if (irq <= 0)
+                               return irq;
+
+                       irqflags |= IRQF_TRIGGER_FALLING;
+               }
        }
 
        INIT_WORK(&alert->alert, smbalert_work);
        alert->ara = ara;
 
        if (irq > 0) {
-               res = devm_request_threaded_irq(&ara->dev, irq,
-                                               NULL, smbus_alert,
-                                               IRQF_SHARED | IRQF_ONESHOT,
-                                               "smbus_alert", alert);
+               res = devm_request_threaded_irq(&ara->dev, irq, NULL, smbus_alert,
+                                               irqflags, "smbus_alert", alert);
                if (res)
                        return res;
        }