]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blobdiff - drivers/i2c/i2c-core-smbus.c
Merge tag 'sunxi-fixes-for-4.15-2' of https://git.kernel.org/pub/scm/linux/kernel...
[mirror_ubuntu-bionic-kernel.git] / drivers / i2c / i2c-core-smbus.c
index 10f00a82ec9dbafaca6c352220655035f117ed00..4bb9927afd0106f6cf6de9fd433c0b66b18173aa 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/device.h>
 #include <linux/err.h>
 #include <linux/i2c.h>
+#include <linux/i2c-smbus.h>
 
 #define CREATE_TRACE_POINTS
 #include <trace/events/smbus.h>
@@ -592,3 +593,57 @@ s32 i2c_smbus_read_i2c_block_data_or_emulated(const struct i2c_client *client,
        return i;
 }
 EXPORT_SYMBOL(i2c_smbus_read_i2c_block_data_or_emulated);
+
+/**
+ * i2c_setup_smbus_alert - Setup SMBus alert support
+ * @adapter: the target adapter
+ * @setup: setup data for the SMBus alert handler
+ * Context: can sleep
+ *
+ * Setup handling of the SMBus alert protocol on a given I2C bus segment.
+ *
+ * Handling can be done either through our IRQ handler, or by the
+ * adapter (from its handler, periodic polling, or whatever).
+ *
+ * NOTE that if we manage the IRQ, we *MUST* know if it's level or
+ * edge triggered in order to hand it to the workqueue correctly.
+ * If triggering the alert seems to wedge the system, you probably
+ * should have said it's level triggered.
+ *
+ * This returns the ara client, which should be saved for later use with
+ * i2c_handle_smbus_alert() and ultimately i2c_unregister_device(); or NULL
+ * to indicate an error.
+ */
+struct i2c_client *i2c_setup_smbus_alert(struct i2c_adapter *adapter,
+                                        struct i2c_smbus_alert_setup *setup)
+{
+       struct i2c_board_info ara_board_info = {
+               I2C_BOARD_INFO("smbus_alert", 0x0c),
+               .platform_data = setup,
+       };
+
+       return i2c_new_device(adapter, &ara_board_info);
+}
+EXPORT_SYMBOL_GPL(i2c_setup_smbus_alert);
+
+#if IS_ENABLED(CONFIG_I2C_SMBUS) && IS_ENABLED(CONFIG_OF)
+int of_i2c_setup_smbus_alert(struct i2c_adapter *adapter)
+{
+       struct i2c_client *client;
+       int irq;
+
+       irq = of_property_match_string(adapter->dev.of_node, "interrupt-names",
+                                      "smbus_alert");
+       if (irq == -EINVAL || irq == -ENODATA)
+               return 0;
+       else if (irq < 0)
+               return irq;
+
+       client = i2c_setup_smbus_alert(adapter, NULL);
+       if (!client)
+               return -ENODEV;
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(of_i2c_setup_smbus_alert);
+#endif