linux/drivers/i2c/i2c-core-of.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * Linux I2C core OF support code
   4 *
   5 * Copyright (C) 2008 Jochen Friedrich <jochen@scram.de>
   6 * based on a previous patch from Jon Smirl <jonsmirl@gmail.com>
   7 *
   8 * Copyright (C) 2013, 2018 Wolfram Sang <wsa@kernel.org>
   9 */
  10
  11#include <dt-bindings/i2c/i2c.h>
  12#include <linux/device.h>
  13#include <linux/err.h>
  14#include <linux/i2c.h>
  15#include <linux/module.h>
  16#include <linux/of.h>
  17#include <linux/of_device.h>
  18#include <linux/sysfs.h>
  19
  20#include "i2c-core.h"
  21
  22int of_i2c_get_board_info(struct device *dev, struct device_node *node,
  23                          struct i2c_board_info *info)
  24{
  25        u32 addr;
  26        int ret;
  27
  28        memset(info, 0, sizeof(*info));
  29
  30        if (of_modalias_node(node, info->type, sizeof(info->type)) < 0) {
  31                dev_err(dev, "of_i2c: modalias failure on %pOF\n", node);
  32                return -EINVAL;
  33        }
  34
  35        ret = of_property_read_u32(node, "reg", &addr);
  36        if (ret) {
  37                dev_err(dev, "of_i2c: invalid reg on %pOF\n", node);
  38                return ret;
  39        }
  40
  41        if (addr & I2C_TEN_BIT_ADDRESS) {
  42                addr &= ~I2C_TEN_BIT_ADDRESS;
  43                info->flags |= I2C_CLIENT_TEN;
  44        }
  45
  46        if (addr & I2C_OWN_SLAVE_ADDRESS) {
  47                addr &= ~I2C_OWN_SLAVE_ADDRESS;
  48                info->flags |= I2C_CLIENT_SLAVE;
  49        }
  50
  51        info->addr = addr;
  52        info->of_node = node;
  53        info->fwnode = of_fwnode_handle(node);
  54
  55        if (of_property_read_bool(node, "host-notify"))
  56                info->flags |= I2C_CLIENT_HOST_NOTIFY;
  57
  58        if (of_get_property(node, "wakeup-source", NULL))
  59                info->flags |= I2C_CLIENT_WAKE;
  60
  61        return 0;
  62}
  63EXPORT_SYMBOL_GPL(of_i2c_get_board_info);
  64
  65static struct i2c_client *of_i2c_register_device(struct i2c_adapter *adap,
  66                                                 struct device_node *node)
  67{
  68        struct i2c_client *client;
  69        struct i2c_board_info info;
  70        int ret;
  71
  72        dev_dbg(&adap->dev, "of_i2c: register %pOF\n", node);
  73
  74        ret = of_i2c_get_board_info(&adap->dev, node, &info);
  75        if (ret)
  76                return ERR_PTR(ret);
  77
  78        client = i2c_new_client_device(adap, &info);
  79        if (IS_ERR(client))
  80                dev_err(&adap->dev, "of_i2c: Failure registering %pOF\n", node);
  81
  82        return client;
  83}
  84
  85void of_i2c_register_devices(struct i2c_adapter *adap)
  86{
  87        struct device_node *bus, *node;
  88        struct i2c_client *client;
  89
  90        /* Only register child devices if the adapter has a node pointer set */
  91        if (!adap->dev.of_node)
  92                return;
  93
  94        dev_dbg(&adap->dev, "of_i2c: walking child nodes\n");
  95
  96        bus = of_get_child_by_name(adap->dev.of_node, "i2c-bus");
  97        if (!bus)
  98                bus = of_node_get(adap->dev.of_node);
  99
 100        for_each_available_child_of_node(bus, node) {
 101                if (of_node_test_and_set_flag(node, OF_POPULATED))
 102                        continue;
 103
 104                client = of_i2c_register_device(adap, node);
 105                if (IS_ERR(client)) {
 106                        dev_err(&adap->dev,
 107                                 "Failed to create I2C device for %pOF\n",
 108                                 node);
 109                        of_node_clear_flag(node, OF_POPULATED);
 110                }
 111        }
 112
 113        of_node_put(bus);
 114}
 115
 116static int of_dev_or_parent_node_match(struct device *dev, const void *data)
 117{
 118        if (dev->of_node == data)
 119                return 1;
 120
 121        if (dev->parent)
 122                return dev->parent->of_node == data;
 123
 124        return 0;
 125}
 126
 127/* must call put_device() when done with returned i2c_client device */
 128struct i2c_client *of_find_i2c_device_by_node(struct device_node *node)
 129{
 130        struct device *dev;
 131        struct i2c_client *client;
 132
 133        dev = bus_find_device_by_of_node(&i2c_bus_type, node);
 134        if (!dev)
 135                return NULL;
 136
 137        client = i2c_verify_client(dev);
 138        if (!client)
 139                put_device(dev);
 140
 141        return client;
 142}
 143EXPORT_SYMBOL(of_find_i2c_device_by_node);
 144
 145/* must call put_device() when done with returned i2c_adapter device */
 146struct i2c_adapter *of_find_i2c_adapter_by_node(struct device_node *node)
 147{
 148        struct device *dev;
 149        struct i2c_adapter *adapter;
 150
 151        dev = bus_find_device(&i2c_bus_type, NULL, node,
 152                              of_dev_or_parent_node_match);
 153        if (!dev)
 154                return NULL;
 155
 156        adapter = i2c_verify_adapter(dev);
 157        if (!adapter)
 158                put_device(dev);
 159
 160        return adapter;
 161}
 162EXPORT_SYMBOL(of_find_i2c_adapter_by_node);
 163
 164/* must call i2c_put_adapter() when done with returned i2c_adapter device */
 165struct i2c_adapter *of_get_i2c_adapter_by_node(struct device_node *node)
 166{
 167        struct i2c_adapter *adapter;
 168
 169        adapter = of_find_i2c_adapter_by_node(node);
 170        if (!adapter)
 171                return NULL;
 172
 173        if (!try_module_get(adapter->owner)) {
 174                put_device(&adapter->dev);
 175                adapter = NULL;
 176        }
 177
 178        return adapter;
 179}
 180EXPORT_SYMBOL(of_get_i2c_adapter_by_node);
 181
 182static const struct of_device_id*
 183i2c_of_match_device_sysfs(const struct of_device_id *matches,
 184                                  struct i2c_client *client)
 185{
 186        const char *name;
 187
 188        for (; matches->compatible[0]; matches++) {
 189                /*
 190                 * Adding devices through the i2c sysfs interface provides us
 191                 * a string to match which may be compatible with the device
 192                 * tree compatible strings, however with no actual of_node the
 193                 * of_match_device() will not match
 194                 */
 195                if (sysfs_streq(client->name, matches->compatible))
 196                        return matches;
 197
 198                name = strchr(matches->compatible, ',');
 199                if (!name)
 200                        name = matches->compatible;
 201                else
 202                        name++;
 203
 204                if (sysfs_streq(client->name, name))
 205                        return matches;
 206        }
 207
 208        return NULL;
 209}
 210
 211const struct of_device_id
 212*i2c_of_match_device(const struct of_device_id *matches,
 213                     struct i2c_client *client)
 214{
 215        const struct of_device_id *match;
 216
 217        if (!(client && matches))
 218                return NULL;
 219
 220        match = of_match_device(matches, &client->dev);
 221        if (match)
 222                return match;
 223
 224        return i2c_of_match_device_sysfs(matches, client);
 225}
 226EXPORT_SYMBOL_GPL(i2c_of_match_device);
 227
 228#if IS_ENABLED(CONFIG_OF_DYNAMIC)
 229static int of_i2c_notify(struct notifier_block *nb, unsigned long action,
 230                         void *arg)
 231{
 232        struct of_reconfig_data *rd = arg;
 233        struct i2c_adapter *adap;
 234        struct i2c_client *client;
 235
 236        switch (of_reconfig_get_state_change(action, rd)) {
 237        case OF_RECONFIG_CHANGE_ADD:
 238                adap = of_find_i2c_adapter_by_node(rd->dn->parent);
 239                if (adap == NULL)
 240                        return NOTIFY_OK;       /* not for us */
 241
 242                if (of_node_test_and_set_flag(rd->dn, OF_POPULATED)) {
 243                        put_device(&adap->dev);
 244                        return NOTIFY_OK;
 245                }
 246
 247                client = of_i2c_register_device(adap, rd->dn);
 248                if (IS_ERR(client)) {
 249                        dev_err(&adap->dev, "failed to create client for '%pOF'\n",
 250                                 rd->dn);
 251                        put_device(&adap->dev);
 252                        of_node_clear_flag(rd->dn, OF_POPULATED);
 253                        return notifier_from_errno(PTR_ERR(client));
 254                }
 255                put_device(&adap->dev);
 256                break;
 257        case OF_RECONFIG_CHANGE_REMOVE:
 258                /* already depopulated? */
 259                if (!of_node_check_flag(rd->dn, OF_POPULATED))
 260                        return NOTIFY_OK;
 261
 262                /* find our device by node */
 263                client = of_find_i2c_device_by_node(rd->dn);
 264                if (client == NULL)
 265                        return NOTIFY_OK;       /* no? not meant for us */
 266
 267                /* unregister takes one ref away */
 268                i2c_unregister_device(client);
 269
 270                /* and put the reference of the find */
 271                put_device(&client->dev);
 272                break;
 273        }
 274
 275        return NOTIFY_OK;
 276}
 277
 278struct notifier_block i2c_of_notifier = {
 279        .notifier_call = of_i2c_notify,
 280};
 281#endif /* CONFIG_OF_DYNAMIC */
 282