Lines Matching +full:i2c +full:- +full:alias
1 // SPDX-License-Identifier: GPL-2.0
3 * I2C Address Translator
8 * Originally based on i2c-mux.c
12 #include <linux/i2c-atr.h>
13 #include <linux/i2c.h>
21 #define ATR_MAX_SYMLINK_LEN 11 /* Longest name is 10 chars: "channel-99" */
24 * struct i2c_atr_alias_pair - Holds the alias assigned to a client.
27 * @alias: I2C alias address assigned by the driver.
28 * This is the address that will be used to issue I2C transactions
34 u16 alias; member
38 * struct i2c_atr_chan - Data for a channel.
40 * @atr: The parent I2C ATR
62 * struct i2c_atr - The I2C ATR instance
64 * @dev: The device that owns the I2C ATR instance
68 * @lock: Lock for the I2C bus segment (see &struct i2c_lock_operations)
69 * @max_adapters: Maximum number of adapters this I2C ATR can have
85 /* lock for the I2C bus segment (see struct i2c_lock_operations) */
107 if (c2a->client == client) in i2c_atr_find_mapping_by_client()
120 if (c2a->client->addr == phys_addr) in i2c_atr_find_mapping_by_addr()
137 struct i2c_atr *atr = chan->atr; in i2c_atr_map_msgs()
142 if (unlikely(chan->orig_addrs_size < num)) { in i2c_atr_map_msgs()
148 return -ENOMEM; in i2c_atr_map_msgs()
150 kfree(chan->orig_addrs); in i2c_atr_map_msgs()
151 chan->orig_addrs = new_buf; in i2c_atr_map_msgs()
152 chan->orig_addrs_size = num; in i2c_atr_map_msgs()
156 chan->orig_addrs[i] = msgs[i].addr; in i2c_atr_map_msgs()
158 c2a = i2c_atr_find_mapping_by_addr(&chan->alias_list, in i2c_atr_map_msgs()
161 dev_err(atr->dev, "client 0x%02x not mapped!\n", in i2c_atr_map_msgs()
164 while (i--) in i2c_atr_map_msgs()
165 msgs[i].addr = chan->orig_addrs[i]; in i2c_atr_map_msgs()
167 return -ENXIO; in i2c_atr_map_msgs()
170 msgs[i].addr = c2a->alias; in i2c_atr_map_msgs()
189 msgs[i].addr = chan->orig_addrs[i]; in i2c_atr_unmap_msgs()
195 struct i2c_atr_chan *chan = adap->algo_data; in i2c_atr_master_xfer()
196 struct i2c_atr *atr = chan->atr; in i2c_atr_master_xfer()
197 struct i2c_adapter *parent = atr->parent; in i2c_atr_master_xfer()
201 mutex_lock(&chan->orig_addrs_lock); in i2c_atr_master_xfer()
214 mutex_unlock(&chan->orig_addrs_lock); in i2c_atr_master_xfer()
223 struct i2c_atr_chan *chan = adap->algo_data; in i2c_atr_smbus_xfer()
224 struct i2c_atr *atr = chan->atr; in i2c_atr_smbus_xfer()
225 struct i2c_adapter *parent = atr->parent; in i2c_atr_smbus_xfer()
228 c2a = i2c_atr_find_mapping_by_addr(&chan->alias_list, addr); in i2c_atr_smbus_xfer()
230 dev_err(atr->dev, "client 0x%02x not mapped!\n", addr); in i2c_atr_smbus_xfer()
231 return -ENXIO; in i2c_atr_smbus_xfer()
234 return i2c_smbus_xfer(parent, c2a->alias, flags, read_write, command, in i2c_atr_smbus_xfer()
240 struct i2c_atr_chan *chan = adap->algo_data; in i2c_atr_functionality()
241 struct i2c_adapter *parent = chan->atr->parent; in i2c_atr_functionality()
243 return parent->algo->functionality(parent); in i2c_atr_functionality()
248 struct i2c_atr_chan *chan = adapter->algo_data; in i2c_atr_lock_bus()
249 struct i2c_atr *atr = chan->atr; in i2c_atr_lock_bus()
251 mutex_lock(&atr->lock); in i2c_atr_lock_bus()
256 struct i2c_atr_chan *chan = adapter->algo_data; in i2c_atr_trylock_bus()
257 struct i2c_atr *atr = chan->atr; in i2c_atr_trylock_bus()
259 return mutex_trylock(&atr->lock); in i2c_atr_trylock_bus()
264 struct i2c_atr_chan *chan = adapter->algo_data; in i2c_atr_unlock_bus()
265 struct i2c_atr *atr = chan->atr; in i2c_atr_unlock_bus()
267 mutex_unlock(&atr->lock); in i2c_atr_unlock_bus()
280 spin_lock(&atr->alias_mask_lock); in i2c_atr_reserve_alias()
282 idx = find_first_zero_bit(atr->alias_use_mask, atr->num_aliases); in i2c_atr_reserve_alias()
283 if (idx >= atr->num_aliases) { in i2c_atr_reserve_alias()
284 spin_unlock(&atr->alias_mask_lock); in i2c_atr_reserve_alias()
285 dev_err(atr->dev, "failed to find a free alias\n"); in i2c_atr_reserve_alias()
286 return -EBUSY; in i2c_atr_reserve_alias()
289 set_bit(idx, atr->alias_use_mask); in i2c_atr_reserve_alias()
291 spin_unlock(&atr->alias_mask_lock); in i2c_atr_reserve_alias()
293 return atr->aliases[idx]; in i2c_atr_reserve_alias()
296 static void i2c_atr_release_alias(struct i2c_atr *atr, u16 alias) in i2c_atr_release_alias() argument
300 spin_lock(&atr->alias_mask_lock); in i2c_atr_release_alias()
302 for (idx = 0; idx < atr->num_aliases; ++idx) { in i2c_atr_release_alias()
303 if (atr->aliases[idx] == alias) { in i2c_atr_release_alias()
304 clear_bit(idx, atr->alias_use_mask); in i2c_atr_release_alias()
305 spin_unlock(&atr->alias_mask_lock); in i2c_atr_release_alias()
310 spin_unlock(&atr->alias_mask_lock); in i2c_atr_release_alias()
313 dev_warn(atr->dev, "Unable to find mapped alias\n"); in i2c_atr_release_alias()
319 struct i2c_atr_chan *chan = adapter->algo_data; in i2c_atr_attach_client()
320 struct i2c_atr *atr = chan->atr; in i2c_atr_attach_client()
322 u16 alias; in i2c_atr_attach_client() local
329 alias = ret; in i2c_atr_attach_client()
333 ret = -ENOMEM; in i2c_atr_attach_client()
337 ret = atr->ops->attach_client(atr, chan->chan_id, client, alias); in i2c_atr_attach_client()
341 dev_dbg(atr->dev, "chan%u: client 0x%02x mapped at alias 0x%02x (%s)\n", in i2c_atr_attach_client()
342 chan->chan_id, client->addr, alias, client->name); in i2c_atr_attach_client()
344 c2a->client = client; in i2c_atr_attach_client()
345 c2a->alias = alias; in i2c_atr_attach_client()
346 list_add(&c2a->node, &chan->alias_list); in i2c_atr_attach_client()
353 i2c_atr_release_alias(atr, alias); in i2c_atr_attach_client()
361 struct i2c_atr_chan *chan = adapter->algo_data; in i2c_atr_detach_client()
362 struct i2c_atr *atr = chan->atr; in i2c_atr_detach_client()
365 atr->ops->detach_client(atr, chan->chan_id, client); in i2c_atr_detach_client()
367 c2a = i2c_atr_find_mapping_by_client(&chan->alias_list, client); in i2c_atr_detach_client()
370 dev_warn(atr->dev, "Unable to find address mapping\n"); in i2c_atr_detach_client()
374 i2c_atr_release_alias(atr, c2a->alias); in i2c_atr_detach_client()
376 dev_dbg(atr->dev, in i2c_atr_detach_client()
377 "chan%u: client 0x%02x unmapped from alias 0x%02x (%s)\n", in i2c_atr_detach_client()
378 chan->chan_id, client->addr, c2a->alias, client->name); in i2c_atr_detach_client()
380 list_del(&c2a->node); in i2c_atr_detach_client()
398 for (chan_id = 0; chan_id < atr->max_adapters; ++chan_id) { in i2c_atr_bus_notifier_call()
399 if (client->adapter == atr->adapter[chan_id]) in i2c_atr_bus_notifier_call()
403 if (chan_id == atr->max_adapters) in i2c_atr_bus_notifier_call()
408 ret = i2c_atr_attach_client(client->adapter, client); in i2c_atr_bus_notifier_call()
410 dev_err(atr->dev, in i2c_atr_bus_notifier_call()
416 i2c_atr_detach_client(client->adapter, client); in i2c_atr_bus_notifier_call()
428 struct device *dev = atr->dev; in i2c_atr_parse_alias_pool()
436 ret = fwnode_property_count_u32(dev_fwnode(dev), "i2c-alias-pool"); in i2c_atr_parse_alias_pool()
438 dev_err(dev, "Failed to count 'i2c-alias-pool' property: %d\n", in i2c_atr_parse_alias_pool()
450 return -ENOMEM; in i2c_atr_parse_alias_pool()
452 ret = fwnode_property_read_u32_array(dev_fwnode(dev), "i2c-alias-pool", in i2c_atr_parse_alias_pool()
455 dev_err(dev, "Failed to read 'i2c-alias-pool' property: %d\n", in i2c_atr_parse_alias_pool()
462 ret = -ENOMEM; in i2c_atr_parse_alias_pool()
472 dev_err(dev, "Failed to parse 'i2c-alias-pool' property: I2C flags are not supported\n"); in i2c_atr_parse_alias_pool()
473 ret = -EINVAL; in i2c_atr_parse_alias_pool()
479 ret = -ENOMEM; in i2c_atr_parse_alias_pool()
485 atr->num_aliases = num_aliases; in i2c_atr_parse_alias_pool()
486 atr->aliases = aliases16; in i2c_atr_parse_alias_pool()
487 atr->alias_use_mask = alias_use_mask; in i2c_atr_parse_alias_pool()
489 dev_dbg(dev, "i2c-alias-pool has %zu aliases", atr->num_aliases); in i2c_atr_parse_alias_pool()
507 return ERR_PTR(-EINVAL); in i2c_atr_new()
509 if (!ops || !ops->attach_client || !ops->detach_client) in i2c_atr_new()
510 return ERR_PTR(-EINVAL); in i2c_atr_new()
514 return ERR_PTR(-ENOMEM); in i2c_atr_new()
516 mutex_init(&atr->lock); in i2c_atr_new()
517 spin_lock_init(&atr->alias_mask_lock); in i2c_atr_new()
519 atr->parent = parent; in i2c_atr_new()
520 atr->dev = dev; in i2c_atr_new()
521 atr->ops = ops; in i2c_atr_new()
522 atr->max_adapters = max_adapters; in i2c_atr_new()
524 if (parent->algo->master_xfer) in i2c_atr_new()
525 atr->algo.master_xfer = i2c_atr_master_xfer; in i2c_atr_new()
526 if (parent->algo->smbus_xfer) in i2c_atr_new()
527 atr->algo.smbus_xfer = i2c_atr_smbus_xfer; in i2c_atr_new()
528 atr->algo.functionality = i2c_atr_functionality; in i2c_atr_new()
534 atr->i2c_nb.notifier_call = i2c_atr_bus_notifier_call; in i2c_atr_new()
535 ret = bus_register_notifier(&i2c_bus_type, &atr->i2c_nb); in i2c_atr_new()
542 bitmap_free(atr->alias_use_mask); in i2c_atr_new()
543 kfree(atr->aliases); in i2c_atr_new()
545 mutex_destroy(&atr->lock); in i2c_atr_new()
556 for (i = 0; i < atr->max_adapters; ++i) in i2c_atr_delete()
557 WARN_ON(atr->adapter[i]); in i2c_atr_delete()
559 bus_unregister_notifier(&i2c_bus_type, &atr->i2c_nb); in i2c_atr_delete()
560 bitmap_free(atr->alias_use_mask); in i2c_atr_delete()
561 kfree(atr->aliases); in i2c_atr_delete()
562 mutex_destroy(&atr->lock); in i2c_atr_delete()
571 struct i2c_adapter *parent = atr->parent; in i2c_atr_add_adapter()
572 struct device *dev = atr->dev; in i2c_atr_add_adapter()
577 if (chan_id >= atr->max_adapters) { in i2c_atr_add_adapter()
578 dev_err(dev, "No room for more i2c-atr adapters\n"); in i2c_atr_add_adapter()
579 return -EINVAL; in i2c_atr_add_adapter()
582 if (atr->adapter[chan_id]) { in i2c_atr_add_adapter()
584 return -EEXIST; in i2c_atr_add_adapter()
589 return -ENOMEM; in i2c_atr_add_adapter()
594 chan->atr = atr; in i2c_atr_add_adapter()
595 chan->chan_id = chan_id; in i2c_atr_add_adapter()
596 INIT_LIST_HEAD(&chan->alias_list); in i2c_atr_add_adapter()
597 mutex_init(&chan->orig_addrs_lock); in i2c_atr_add_adapter()
599 snprintf(chan->adap.name, sizeof(chan->adap.name), "i2c-%d-atr-%d", in i2c_atr_add_adapter()
601 chan->adap.owner = THIS_MODULE; in i2c_atr_add_adapter()
602 chan->adap.algo = &atr->algo; in i2c_atr_add_adapter()
603 chan->adap.algo_data = chan; in i2c_atr_add_adapter()
604 chan->adap.dev.parent = adapter_parent; in i2c_atr_add_adapter()
605 chan->adap.retries = parent->retries; in i2c_atr_add_adapter()
606 chan->adap.timeout = parent->timeout; in i2c_atr_add_adapter()
607 chan->adap.quirks = parent->quirks; in i2c_atr_add_adapter()
608 chan->adap.lock_ops = &i2c_atr_lock_ops; in i2c_atr_add_adapter()
611 device_set_node(&chan->adap.dev, fwnode_handle_get(bus_handle)); in i2c_atr_add_adapter()
617 atr_node = device_get_named_child_node(dev, "i2c-atr"); in i2c_atr_add_adapter()
627 device_set_node(&chan->adap.dev, child); in i2c_atr_add_adapter()
631 atr->adapter[chan_id] = &chan->adap; in i2c_atr_add_adapter()
633 ret = i2c_add_adapter(&chan->adap); in i2c_atr_add_adapter()
635 dev_err(dev, "failed to add atr-adapter %u (error=%d)\n", in i2c_atr_add_adapter()
640 snprintf(symlink_name, sizeof(symlink_name), "channel-%u", in i2c_atr_add_adapter()
641 chan->chan_id); in i2c_atr_add_adapter()
643 ret = sysfs_create_link(&chan->adap.dev.kobj, &dev->kobj, "atr_device"); in i2c_atr_add_adapter()
646 ret = sysfs_create_link(&dev->kobj, &chan->adap.dev.kobj, symlink_name); in i2c_atr_add_adapter()
650 dev_dbg(dev, "Added ATR child bus %d\n", i2c_adapter_id(&chan->adap)); in i2c_atr_add_adapter()
655 fwnode_handle_put(dev_fwnode(&chan->adap.dev)); in i2c_atr_add_adapter()
656 mutex_destroy(&chan->orig_addrs_lock); in i2c_atr_add_adapter()
668 struct device *dev = atr->dev; in i2c_atr_del_adapter()
670 adap = atr->adapter[chan_id]; in i2c_atr_del_adapter()
674 chan = adap->algo_data; in i2c_atr_del_adapter()
675 fwnode = dev_fwnode(&adap->dev); in i2c_atr_del_adapter()
679 snprintf(symlink_name, sizeof(symlink_name), "channel-%u", in i2c_atr_del_adapter()
680 chan->chan_id); in i2c_atr_del_adapter()
681 sysfs_remove_link(&dev->kobj, symlink_name); in i2c_atr_del_adapter()
682 sysfs_remove_link(&chan->adap.dev.kobj, "atr_device"); in i2c_atr_del_adapter()
686 atr->adapter[chan_id] = NULL; in i2c_atr_del_adapter()
689 mutex_destroy(&chan->orig_addrs_lock); in i2c_atr_del_adapter()
690 kfree(chan->orig_addrs); in i2c_atr_del_adapter()
697 atr->priv = data; in i2c_atr_set_driver_data()
703 return atr->priv; in i2c_atr_get_driver_data()
709 MODULE_DESCRIPTION("I2C Address Translator");