• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Linux I2C core slave support code
4  *
5  * Copyright (C) 2014 by Wolfram Sang <wsa@sang-engineering.com>
6  */
7 
8 #include <dt-bindings/i2c/i2c.h>
9 #include <linux/acpi.h>
10 #include <linux/device.h>
11 #include <linux/err.h>
12 #include <linux/i2c.h>
13 #include <linux/of.h>
14 
15 #include "i2c-core.h"
16 
i2c_slave_register(struct i2c_client * client,i2c_slave_cb_t slave_cb)17 int i2c_slave_register(struct i2c_client *client, i2c_slave_cb_t slave_cb)
18 {
19 	int ret;
20 
21 	if (WARN(IS_ERR_OR_NULL(client) || !slave_cb, "insufficient data\n"))
22 		return -EINVAL;
23 
24 	if (!(client->flags & I2C_CLIENT_SLAVE))
25 		dev_warn(&client->dev, "%s: client slave flag not set. You might see address collisions\n",
26 			 __func__);
27 
28 	if (!(client->flags & I2C_CLIENT_TEN)) {
29 		/* Enforce stricter address checking */
30 		ret = i2c_check_7bit_addr_validity_strict(client->addr);
31 		if (ret) {
32 			dev_err(&client->dev, "%s: invalid address\n", __func__);
33 			return ret;
34 		}
35 	}
36 
37 	if (!client->adapter->algo->reg_slave) {
38 		dev_err(&client->dev, "%s: not supported by adapter\n", __func__);
39 		return -EOPNOTSUPP;
40 	}
41 
42 	client->slave_cb = slave_cb;
43 
44 	i2c_lock_bus(client->adapter, I2C_LOCK_ROOT_ADAPTER);
45 	ret = client->adapter->algo->reg_slave(client);
46 	i2c_unlock_bus(client->adapter, I2C_LOCK_ROOT_ADAPTER);
47 
48 	if (ret) {
49 		client->slave_cb = NULL;
50 		dev_err(&client->dev, "%s: adapter returned error %d\n", __func__, ret);
51 	}
52 
53 	return ret;
54 }
55 EXPORT_SYMBOL_GPL(i2c_slave_register);
56 
i2c_slave_unregister(struct i2c_client * client)57 int i2c_slave_unregister(struct i2c_client *client)
58 {
59 	int ret;
60 
61 	if (IS_ERR_OR_NULL(client))
62 		return -EINVAL;
63 
64 	if (!client->adapter->algo->unreg_slave) {
65 		dev_err(&client->dev, "%s: not supported by adapter\n", __func__);
66 		return -EOPNOTSUPP;
67 	}
68 
69 	i2c_lock_bus(client->adapter, I2C_LOCK_ROOT_ADAPTER);
70 	ret = client->adapter->algo->unreg_slave(client);
71 	i2c_unlock_bus(client->adapter, I2C_LOCK_ROOT_ADAPTER);
72 
73 	if (ret == 0)
74 		client->slave_cb = NULL;
75 	else
76 		dev_err(&client->dev, "%s: adapter returned error %d\n", __func__, ret);
77 
78 	return ret;
79 }
80 EXPORT_SYMBOL_GPL(i2c_slave_unregister);
81 
82 /**
83  * i2c_detect_slave_mode - detect operation mode
84  * @dev: The device owning the bus
85  *
86  * This checks the device nodes for an I2C slave by checking the address
87  * used in the reg property. If the address match the I2C_OWN_SLAVE_ADDRESS
88  * flag this means the device is configured to act as a I2C slave and it will
89  * be listening at that address.
90  *
91  * Returns true if an I2C own slave address is detected, otherwise returns
92  * false.
93  */
i2c_detect_slave_mode(struct device * dev)94 bool i2c_detect_slave_mode(struct device *dev)
95 {
96 	if (IS_BUILTIN(CONFIG_OF) && dev->of_node) {
97 		struct device_node *child;
98 		u32 reg;
99 
100 		for_each_child_of_node(dev->of_node, child) {
101 			of_property_read_u32(child, "reg", &reg);
102 			if (reg & I2C_OWN_SLAVE_ADDRESS) {
103 				of_node_put(child);
104 				return true;
105 			}
106 		}
107 	} else if (IS_BUILTIN(CONFIG_ACPI) && ACPI_HANDLE(dev)) {
108 		dev_dbg(dev, "ACPI slave is not supported yet\n");
109 	}
110 	return false;
111 }
112 EXPORT_SYMBOL_GPL(i2c_detect_slave_mode);
113