Skip to content

Commit 270cc3c

Browse files
author
Wolfram Sang
committed
i2c: support gpio-binding for SMBAlerts
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>
1 parent 6b238b3 commit 270cc3c

File tree

2 files changed

+22
-9
lines changed

2 files changed

+22
-9
lines changed

drivers/i2c/i2c-core-smbus.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -712,12 +712,15 @@ int i2c_setup_smbus_alert(struct i2c_adapter *adapter)
712712
if (!parent)
713713
return 0;
714714

715+
/* Report serious errors */
715716
irq = device_property_match_string(parent, "interrupt-names", "smbus_alert");
716-
if (irq == -EINVAL || irq == -ENODATA)
717-
return 0;
718-
else if (irq < 0)
717+
if (irq < 0 && irq != -EINVAL && irq != -ENODATA)
719718
return irq;
720719

720+
/* Skip setup when no irq was found */
721+
if (irq < 0 && !device_property_present(parent, "smbalert-gpios"))
722+
return 0;
723+
721724
return PTR_ERR_OR_ZERO(i2c_new_smbus_alert_device(adapter, NULL));
722725
}
723726
#endif

drivers/i2c/i2c-smbus.c

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
#include <linux/device.h>
1010
#include <linux/dmi.h>
11+
#include <linux/gpio/consumer.h>
1112
#include <linux/i2c.h>
1213
#include <linux/i2c-smbus.h>
1314
#include <linux/interrupt.h>
@@ -167,6 +168,8 @@ static int smbalert_probe(struct i2c_client *ara)
167168
struct i2c_smbus_alert_setup *setup = dev_get_platdata(&ara->dev);
168169
struct i2c_smbus_alert *alert;
169170
struct i2c_adapter *adapter = ara->adapter;
171+
unsigned long irqflags = IRQF_SHARED | IRQF_ONESHOT;
172+
struct gpio_desc *gpiod;
170173
int res, irq;
171174

172175
alert = devm_kzalloc(&ara->dev, sizeof(struct i2c_smbus_alert),
@@ -179,18 +182,25 @@ static int smbalert_probe(struct i2c_client *ara)
179182
} else {
180183
irq = fwnode_irq_get_byname(dev_fwnode(adapter->dev.parent),
181184
"smbus_alert");
182-
if (irq <= 0)
183-
return irq;
185+
if (irq <= 0) {
186+
gpiod = devm_gpiod_get(adapter->dev.parent, "smbalert", GPIOD_IN);
187+
if (IS_ERR(gpiod))
188+
return PTR_ERR(gpiod);
189+
190+
irq = gpiod_to_irq(gpiod);
191+
if (irq <= 0)
192+
return irq;
193+
194+
irqflags |= IRQF_TRIGGER_FALLING;
195+
}
184196
}
185197

186198
INIT_WORK(&alert->alert, smbalert_work);
187199
alert->ara = ara;
188200

189201
if (irq > 0) {
190-
res = devm_request_threaded_irq(&ara->dev, irq,
191-
NULL, smbus_alert,
192-
IRQF_SHARED | IRQF_ONESHOT,
193-
"smbus_alert", alert);
202+
res = devm_request_threaded_irq(&ara->dev, irq, NULL, smbus_alert,
203+
irqflags, "smbus_alert", alert);
194204
if (res)
195205
return res;
196206
}

0 commit comments

Comments
 (0)