linux/drivers/i2c/i2c-core-slave.c
<<
>>
Prefs
   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
  17int 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}
  55EXPORT_SYMBOL_GPL(i2c_slave_register);
  56
  57int 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}
  80EXPORT_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 */
  94bool 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}
 112EXPORT_SYMBOL_GPL(i2c_detect_slave_mode);
 113