summaryrefslogtreecommitdiff
path: root/drivers/i2c/i2c-core-slave.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2017-07-12 20:04:56 +0300
committerLinus Torvalds <torvalds@linux-foundation.org>2017-07-12 20:04:56 +0300
commit235b84fc862ae2637dc0dabada18d97f1bfc18e1 (patch)
treec89a1a8ffa7765fc7fa7cfe1ba4c033eb886a87d /drivers/i2c/i2c-core-slave.c
parentfb4e3beeffa47619985f190663c6ef424f063a22 (diff)
parent8f1a357d41a22009150cf404b5aa5876efdb59b1 (diff)
downloadlinux-235b84fc862ae2637dc0dabada18d97f1bfc18e1.tar.xz
Merge branch 'i2c/for-4.13' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux
Pull i2c updates from Wolfram Sang: "This pull request contains: - i2c core reorganization. One source file became too monolithic. It is now split up, yet we still have the same named object as the final output. This should ease maintenance. - new drivers: ZTE ZX2967 family, ASPEED 24XX/25XX - designware driver gained slave mode support - xgene-slimpro driver gained ACPI support - bigger overhaul for pca-platform driver - the algo-bit module now supports messages with enforced STOP - slightly bigger than usual set of driver updates and improvements and with much appreciated quality assurance from Andy Shevchenko" * 'i2c/for-4.13' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux: (51 commits) i2c: Provide a stub for i2c_detect_slave_mode() i2c: designware: Let slave adapter support be optional i2c: designware: Make HW init functions static i2c: designware: fix spelling mistakes i2c: pca-platform: propagate error from i2c_pca_add_numbered_bus i2c: pca-platform: correctly set algo_data.reset_chip i2c: acpi: Do not create i2c-clients for LNXVIDEO ACPI devices i2c: designware: enable SLAVE in platform module i2c: designware: add SLAVE mode functions i2c: zx2967: drop COMPILE_TEST dependency i2c: zx2967: always use the same device when printing errors i2c: pca-platform: use dev_warn/dev_info instead of printk i2c: pca-platform: use device managed allocations i2c: pca-platform: add devicetree awareness i2c: pca-platform: switch to struct gpio_desc dt-bindings: add bindings for i2c-pca-platform i2c: cadance: fix ctrl/addr reg write order i2c: zx2967: add i2c controller driver for ZTE's zx2967 family dt: bindings: add documentation for zx2967 family i2c controller i2c: algo-bit: add support for I2C_M_STOP ...
Diffstat (limited to 'drivers/i2c/i2c-core-slave.c')
-rw-r--r--drivers/i2c/i2c-core-slave.c115
1 files changed, 115 insertions, 0 deletions
diff --git a/drivers/i2c/i2c-core-slave.c b/drivers/i2c/i2c-core-slave.c
new file mode 100644
index 000000000000..4a78c65e9971
--- /dev/null
+++ b/drivers/i2c/i2c-core-slave.c
@@ -0,0 +1,115 @@
+/*
+ * Linux I2C core slave support code
+ *
+ * Copyright (C) 2014 by Wolfram Sang <wsa@sang-engineering.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ */
+
+#include <dt-bindings/i2c/i2c.h>
+#include <linux/acpi.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/of.h>
+
+#include "i2c-core.h"
+
+int i2c_slave_register(struct i2c_client *client, i2c_slave_cb_t slave_cb)
+{
+ int ret;
+
+ if (!client || !slave_cb) {
+ WARN(1, "insufficient data\n");
+ return -EINVAL;
+ }
+
+ if (!(client->flags & I2C_CLIENT_SLAVE))
+ dev_warn(&client->dev, "%s: client slave flag not set. You might see address collisions\n",
+ __func__);
+
+ if (!(client->flags & I2C_CLIENT_TEN)) {
+ /* Enforce stricter address checking */
+ ret = i2c_check_7bit_addr_validity_strict(client->addr);
+ if (ret) {
+ dev_err(&client->dev, "%s: invalid address\n", __func__);
+ return ret;
+ }
+ }
+
+ if (!client->adapter->algo->reg_slave) {
+ dev_err(&client->dev, "%s: not supported by adapter\n", __func__);
+ return -EOPNOTSUPP;
+ }
+
+ client->slave_cb = slave_cb;
+
+ i2c_lock_adapter(client->adapter);
+ ret = client->adapter->algo->reg_slave(client);
+ i2c_unlock_adapter(client->adapter);
+
+ if (ret) {
+ client->slave_cb = NULL;
+ dev_err(&client->dev, "%s: adapter returned error %d\n", __func__, ret);
+ }
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(i2c_slave_register);
+
+int i2c_slave_unregister(struct i2c_client *client)
+{
+ int ret;
+
+ if (!client->adapter->algo->unreg_slave) {
+ dev_err(&client->dev, "%s: not supported by adapter\n", __func__);
+ return -EOPNOTSUPP;
+ }
+
+ i2c_lock_adapter(client->adapter);
+ ret = client->adapter->algo->unreg_slave(client);
+ i2c_unlock_adapter(client->adapter);
+
+ if (ret == 0)
+ client->slave_cb = NULL;
+ else
+ dev_err(&client->dev, "%s: adapter returned error %d\n", __func__, ret);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(i2c_slave_unregister);
+
+/**
+ * i2c_detect_slave_mode - detect operation mode
+ * @dev: The device owning the bus
+ *
+ * This checks the device nodes for an I2C slave by checking the address
+ * used in the reg property. If the address match the I2C_OWN_SLAVE_ADDRESS
+ * flag this means the device is configured to act as a I2C slave and it will
+ * be listening at that address.
+ *
+ * Returns true if an I2C own slave address is detected, otherwise returns
+ * false.
+ */
+bool i2c_detect_slave_mode(struct device *dev)
+{
+ if (IS_BUILTIN(CONFIG_OF) && dev->of_node) {
+ struct device_node *child;
+ u32 reg;
+
+ for_each_child_of_node(dev->of_node, child) {
+ of_property_read_u32(child, "reg", &reg);
+ if (reg & I2C_OWN_SLAVE_ADDRESS) {
+ of_node_put(child);
+ return true;
+ }
+ }
+ } else if (IS_BUILTIN(CONFIG_ACPI) && ACPI_HANDLE(dev)) {
+ dev_dbg(dev, "ACPI slave is not supported yet\n");
+ }
+ return false;
+}
+EXPORT_SYMBOL_GPL(i2c_detect_slave_mode);