Lines Matching +full:num +full:- +full:addresses
1 // SPDX-License-Identifier: GPL-2.0
8 * Originally based on i2c-mux.c
11 #include <linux/i2c-atr.h>
22 #define ATR_MAX_SYMLINK_LEN 11 /* Longest name is 10 chars: "channel-99" */
25 * struct i2c_atr_alias_pair - Holds the alias assigned to a client address.
33 * contains more distinct target addresses than the ATR channel can handle.
34 * It marks addresses that have already been attached to an alias so
47 * struct i2c_atr_alias_pool - Pool of client aliases available for an ATR.
66 * struct i2c_atr_chan - Data for a channel.
78 * @orig_addrs: Buffer used to store the original addresses during transmit
100 * struct i2c_atr - The I2C ATR instance
142 return ERR_PTR(-ENOMEM); in i2c_atr_alloc_alias_pool()
144 alias_pool->size = num_aliases; in i2c_atr_alloc_alias_pool()
146 alias_pool->aliases = kcalloc(num_aliases, sizeof(*alias_pool->aliases), GFP_KERNEL); in i2c_atr_alloc_alias_pool()
147 if (!alias_pool->aliases) { in i2c_atr_alloc_alias_pool()
148 ret = -ENOMEM; in i2c_atr_alloc_alias_pool()
152 alias_pool->use_mask = bitmap_zalloc(num_aliases, GFP_KERNEL); in i2c_atr_alloc_alias_pool()
153 if (!alias_pool->use_mask) { in i2c_atr_alloc_alias_pool()
154 ret = -ENOMEM; in i2c_atr_alloc_alias_pool()
158 alias_pool->shared = shared; in i2c_atr_alloc_alias_pool()
160 spin_lock_init(&alias_pool->lock); in i2c_atr_alloc_alias_pool()
165 kfree(alias_pool->aliases); in i2c_atr_alloc_alias_pool()
173 bitmap_free(alias_pool->use_mask); in i2c_atr_free_alias_pool()
174 kfree(alias_pool->aliases); in i2c_atr_free_alias_pool()
184 lockdep_assert_held(&chan->alias_pairs_lock); in i2c_atr_create_c2a()
190 c2a->addr = addr; in i2c_atr_create_c2a()
191 c2a->alias = alias; in i2c_atr_create_c2a()
193 list_add(&c2a->node, &chan->alias_pairs); in i2c_atr_create_c2a()
201 list_del(&(*pc2a)->node); in i2c_atr_destroy_c2a()
211 spin_lock(&alias_pool->lock); in i2c_atr_reserve_alias()
213 idx = find_first_zero_bit(alias_pool->use_mask, alias_pool->size); in i2c_atr_reserve_alias()
214 if (idx >= alias_pool->size) { in i2c_atr_reserve_alias()
215 spin_unlock(&alias_pool->lock); in i2c_atr_reserve_alias()
216 return -EBUSY; in i2c_atr_reserve_alias()
219 set_bit(idx, alias_pool->use_mask); in i2c_atr_reserve_alias()
221 alias = alias_pool->aliases[idx]; in i2c_atr_reserve_alias()
223 spin_unlock(&alias_pool->lock); in i2c_atr_reserve_alias()
231 spin_lock(&alias_pool->lock); in i2c_atr_release_alias()
233 for (idx = 0; idx < alias_pool->size; ++idx) { in i2c_atr_release_alias()
234 if (alias_pool->aliases[idx] == alias) { in i2c_atr_release_alias()
235 clear_bit(idx, alias_pool->use_mask); in i2c_atr_release_alias()
236 spin_unlock(&alias_pool->lock); in i2c_atr_release_alias()
241 spin_unlock(&alias_pool->lock); in i2c_atr_release_alias()
249 lockdep_assert_held(&chan->alias_pairs_lock); in i2c_atr_find_mapping_by_addr()
251 list_for_each_entry(c2a, &chan->alias_pairs, node) { in i2c_atr_find_mapping_by_addr()
252 if (c2a->addr == addr) in i2c_atr_find_mapping_by_addr()
262 struct i2c_atr *atr = chan->atr; in i2c_atr_create_mapping_by_addr()
267 lockdep_assert_held(&chan->alias_pairs_lock); in i2c_atr_create_mapping_by_addr()
269 ret = i2c_atr_reserve_alias(chan->alias_pool); in i2c_atr_create_mapping_by_addr()
279 ret = atr->ops->attach_addr(atr, chan->chan_id, c2a->addr, c2a->alias); in i2c_atr_create_mapping_by_addr()
281 dev_err(atr->dev, "failed to attach 0x%02x on channel %d: err %d\n", in i2c_atr_create_mapping_by_addr()
282 addr, chan->chan_id, ret); in i2c_atr_create_mapping_by_addr()
291 i2c_atr_release_alias(chan->alias_pool, alias); in i2c_atr_create_mapping_by_addr()
298 struct i2c_atr *atr = chan->atr; in i2c_atr_replace_mapping_by_addr()
305 lockdep_assert_held(&chan->alias_pairs_lock); in i2c_atr_replace_mapping_by_addr()
307 alias_pairs = &chan->alias_pairs; in i2c_atr_replace_mapping_by_addr()
313 if (!c2a->fixed) { in i2c_atr_replace_mapping_by_addr()
322 atr->ops->detach_addr(atr, chan->chan_id, c2a->addr); in i2c_atr_replace_mapping_by_addr()
323 c2a->addr = addr; in i2c_atr_replace_mapping_by_addr()
325 list_move(&c2a->node, alias_pairs); in i2c_atr_replace_mapping_by_addr()
327 alias = c2a->alias; in i2c_atr_replace_mapping_by_addr()
329 ret = atr->ops->attach_addr(atr, chan->chan_id, c2a->addr, c2a->alias); in i2c_atr_replace_mapping_by_addr()
331 dev_err(atr->dev, "failed to attach 0x%02x on channel %d: err %d\n", in i2c_atr_replace_mapping_by_addr()
332 addr, chan->chan_id, ret); in i2c_atr_replace_mapping_by_addr()
334 i2c_atr_release_alias(chan->alias_pool, alias); in i2c_atr_replace_mapping_by_addr()
344 struct i2c_atr *atr = chan->atr; in i2c_atr_get_mapping_by_addr()
351 if (atr->flags & I2C_ATR_F_STATIC) in i2c_atr_get_mapping_by_addr()
362 * Replace all message addresses with their aliases, saving the original
363 * addresses.
366 * followed by i2c_atr_unmap_msgs() to restore the original addresses.
369 int num) in i2c_atr_map_msgs() argument
371 struct i2c_atr *atr = chan->atr; in i2c_atr_map_msgs()
375 /* Ensure we have enough room to save the original addresses */ in i2c_atr_map_msgs()
376 if (unlikely(chan->orig_addrs_size < num)) { in i2c_atr_map_msgs()
380 new_buf = kmalloc_array(num, sizeof(*new_buf), GFP_KERNEL); in i2c_atr_map_msgs()
382 return -ENOMEM; in i2c_atr_map_msgs()
384 kfree(chan->orig_addrs); in i2c_atr_map_msgs()
385 chan->orig_addrs = new_buf; in i2c_atr_map_msgs()
386 chan->orig_addrs_size = num; in i2c_atr_map_msgs()
389 mutex_lock(&chan->alias_pairs_lock); in i2c_atr_map_msgs()
391 for (i = 0; i < num; i++) { in i2c_atr_map_msgs()
392 chan->orig_addrs[i] = msgs[i].addr; in i2c_atr_map_msgs()
397 if (atr->flags & I2C_ATR_F_PASSTHROUGH) in i2c_atr_map_msgs()
400 dev_err(atr->dev, "client 0x%02x not mapped!\n", in i2c_atr_map_msgs()
403 while (i--) in i2c_atr_map_msgs()
404 msgs[i].addr = chan->orig_addrs[i]; in i2c_atr_map_msgs()
406 ret = -ENXIO; in i2c_atr_map_msgs()
411 c2a->fixed = true; in i2c_atr_map_msgs()
413 msgs[i].addr = c2a->alias; in i2c_atr_map_msgs()
417 mutex_unlock(&chan->alias_pairs_lock); in i2c_atr_map_msgs()
422 * Restore all message address aliases with the original addresses. This
429 int num) in i2c_atr_unmap_msgs() argument
434 for (i = 0; i < num; i++) in i2c_atr_unmap_msgs()
435 msgs[i].addr = chan->orig_addrs[i]; in i2c_atr_unmap_msgs()
437 mutex_lock(&chan->alias_pairs_lock); in i2c_atr_unmap_msgs()
439 if (unlikely(list_empty(&chan->alias_pairs))) in i2c_atr_unmap_msgs()
443 list_for_each_entry(c2a, &chan->alias_pairs, node) { in i2c_atr_unmap_msgs()
444 c2a->fixed = false; in i2c_atr_unmap_msgs()
448 mutex_unlock(&chan->alias_pairs_lock); in i2c_atr_unmap_msgs()
452 int num) in i2c_atr_master_xfer() argument
454 struct i2c_atr_chan *chan = adap->algo_data; in i2c_atr_master_xfer()
455 struct i2c_atr *atr = chan->atr; in i2c_atr_master_xfer()
456 struct i2c_adapter *parent = atr->parent; in i2c_atr_master_xfer()
459 /* Translate addresses */ in i2c_atr_master_xfer()
460 mutex_lock(&chan->orig_addrs_lock); in i2c_atr_master_xfer()
462 ret = i2c_atr_map_msgs(chan, msgs, num); in i2c_atr_master_xfer()
467 ret = i2c_transfer(parent, msgs, num); in i2c_atr_master_xfer()
469 /* Restore addresses */ in i2c_atr_master_xfer()
470 i2c_atr_unmap_msgs(chan, msgs, num); in i2c_atr_master_xfer()
473 mutex_unlock(&chan->orig_addrs_lock); in i2c_atr_master_xfer()
482 struct i2c_atr_chan *chan = adap->algo_data; in i2c_atr_smbus_xfer()
483 struct i2c_atr *atr = chan->atr; in i2c_atr_smbus_xfer()
484 struct i2c_adapter *parent = atr->parent; in i2c_atr_smbus_xfer()
488 mutex_lock(&chan->alias_pairs_lock); in i2c_atr_smbus_xfer()
492 if (!c2a && !(atr->flags & I2C_ATR_F_PASSTHROUGH)) { in i2c_atr_smbus_xfer()
493 dev_err(atr->dev, "client 0x%02x not mapped!\n", addr); in i2c_atr_smbus_xfer()
494 mutex_unlock(&chan->alias_pairs_lock); in i2c_atr_smbus_xfer()
495 return -ENXIO; in i2c_atr_smbus_xfer()
498 alias = c2a ? c2a->alias : addr; in i2c_atr_smbus_xfer()
500 mutex_unlock(&chan->alias_pairs_lock); in i2c_atr_smbus_xfer()
508 struct i2c_atr_chan *chan = adap->algo_data; in i2c_atr_functionality()
509 struct i2c_adapter *parent = chan->atr->parent; in i2c_atr_functionality()
511 return parent->algo->functionality(parent); in i2c_atr_functionality()
516 struct i2c_atr_chan *chan = adapter->algo_data; in i2c_atr_lock_bus()
517 struct i2c_atr *atr = chan->atr; in i2c_atr_lock_bus()
519 mutex_lock(&atr->lock); in i2c_atr_lock_bus()
524 struct i2c_atr_chan *chan = adapter->algo_data; in i2c_atr_trylock_bus()
525 struct i2c_atr *atr = chan->atr; in i2c_atr_trylock_bus()
527 return mutex_trylock(&atr->lock); in i2c_atr_trylock_bus()
532 struct i2c_atr_chan *chan = adapter->algo_data; in i2c_atr_unlock_bus()
533 struct i2c_atr *atr = chan->atr; in i2c_atr_unlock_bus()
535 mutex_unlock(&atr->lock); in i2c_atr_unlock_bus()
547 struct i2c_atr_chan *chan = adapter->algo_data; in i2c_atr_attach_addr()
548 struct i2c_atr *atr = chan->atr; in i2c_atr_attach_addr()
552 mutex_lock(&chan->alias_pairs_lock); in i2c_atr_attach_addr()
555 if (!c2a && !(atr->flags & I2C_ATR_F_STATIC)) in i2c_atr_attach_addr()
559 dev_err(atr->dev, "failed to find a free alias\n"); in i2c_atr_attach_addr()
560 ret = -EBUSY; in i2c_atr_attach_addr()
564 dev_dbg(atr->dev, "chan%u: using alias 0x%02x for addr 0x%02x\n", in i2c_atr_attach_addr()
565 chan->chan_id, c2a->alias, addr); in i2c_atr_attach_addr()
568 mutex_unlock(&chan->alias_pairs_lock); in i2c_atr_attach_addr()
575 struct i2c_atr_chan *chan = adapter->algo_data; in i2c_atr_detach_addr()
576 struct i2c_atr *atr = chan->atr; in i2c_atr_detach_addr()
579 atr->ops->detach_addr(atr, chan->chan_id, addr); in i2c_atr_detach_addr()
581 mutex_lock(&chan->alias_pairs_lock); in i2c_atr_detach_addr()
585 mutex_unlock(&chan->alias_pairs_lock); in i2c_atr_detach_addr()
589 i2c_atr_release_alias(chan->alias_pool, c2a->alias); in i2c_atr_detach_addr()
591 dev_dbg(atr->dev, in i2c_atr_detach_addr()
593 chan->chan_id, c2a->alias, addr); in i2c_atr_detach_addr()
597 mutex_unlock(&chan->alias_pairs_lock); in i2c_atr_detach_addr()
614 for (chan_id = 0; chan_id < atr->max_adapters; ++chan_id) { in i2c_atr_bus_notifier_call()
615 if (client->adapter == atr->adapter[chan_id]) in i2c_atr_bus_notifier_call()
619 if (chan_id == atr->max_adapters) in i2c_atr_bus_notifier_call()
624 ret = i2c_atr_attach_addr(client->adapter, client->addr); in i2c_atr_bus_notifier_call()
626 dev_err(atr->dev, in i2c_atr_bus_notifier_call()
632 i2c_atr_detach_addr(client->adapter, client->addr); in i2c_atr_bus_notifier_call()
645 struct device *dev = atr->dev; in i2c_atr_parse_alias_pool()
651 if (!fwnode_property_present(dev_fwnode(dev), "i2c-alias-pool")) { in i2c_atr_parse_alias_pool()
654 ret = fwnode_property_count_u32(dev_fwnode(dev), "i2c-alias-pool"); in i2c_atr_parse_alias_pool()
656 dev_err(dev, "Failed to count 'i2c-alias-pool' property: %d\n", in i2c_atr_parse_alias_pool()
671 atr->alias_pool = alias_pool; in i2c_atr_parse_alias_pool()
673 if (!alias_pool->size) in i2c_atr_parse_alias_pool()
678 ret = -ENOMEM; in i2c_atr_parse_alias_pool()
682 ret = fwnode_property_read_u32_array(dev_fwnode(dev), "i2c-alias-pool", in i2c_atr_parse_alias_pool()
685 dev_err(dev, "Failed to read 'i2c-alias-pool' property: %d\n", in i2c_atr_parse_alias_pool()
692 alias_pool->aliases[i] = aliases32[i]; in i2c_atr_parse_alias_pool()
696 dev_err(dev, "Failed to parse 'i2c-alias-pool' property: I2C flags are not supported\n"); in i2c_atr_parse_alias_pool()
697 ret = -EINVAL; in i2c_atr_parse_alias_pool()
703 dev_dbg(dev, "i2c-alias-pool has %zu aliases\n", alias_pool->size); in i2c_atr_parse_alias_pool()
722 return ERR_PTR(-EINVAL); in i2c_atr_new()
724 if (!ops || !ops->attach_addr || !ops->detach_addr) in i2c_atr_new()
725 return ERR_PTR(-EINVAL); in i2c_atr_new()
729 return ERR_PTR(-ENOMEM); in i2c_atr_new()
731 lockdep_register_key(&atr->lock_key); in i2c_atr_new()
732 mutex_init_with_key(&atr->lock, &atr->lock_key); in i2c_atr_new()
734 atr->parent = parent; in i2c_atr_new()
735 atr->dev = dev; in i2c_atr_new()
736 atr->ops = ops; in i2c_atr_new()
737 atr->max_adapters = max_adapters; in i2c_atr_new()
738 atr->flags = flags; in i2c_atr_new()
740 if (parent->algo->master_xfer) in i2c_atr_new()
741 atr->algo.xfer = i2c_atr_master_xfer; in i2c_atr_new()
742 if (parent->algo->smbus_xfer) in i2c_atr_new()
743 atr->algo.smbus_xfer = i2c_atr_smbus_xfer; in i2c_atr_new()
744 atr->algo.functionality = i2c_atr_functionality; in i2c_atr_new()
750 atr->i2c_nb.notifier_call = i2c_atr_bus_notifier_call; in i2c_atr_new()
751 ret = bus_register_notifier(&i2c_bus_type, &atr->i2c_nb); in i2c_atr_new()
758 i2c_atr_free_alias_pool(atr->alias_pool); in i2c_atr_new()
760 mutex_destroy(&atr->lock); in i2c_atr_new()
761 lockdep_unregister_key(&atr->lock_key); in i2c_atr_new()
772 for (i = 0; i < atr->max_adapters; ++i) in i2c_atr_delete()
773 WARN_ON(atr->adapter[i]); in i2c_atr_delete()
775 bus_unregister_notifier(&i2c_bus_type, &atr->i2c_nb); in i2c_atr_delete()
776 i2c_atr_free_alias_pool(atr->alias_pool); in i2c_atr_delete()
777 mutex_destroy(&atr->lock); in i2c_atr_delete()
778 lockdep_unregister_key(&atr->lock_key); in i2c_atr_delete()
785 struct fwnode_handle *bus_handle = desc->bus_handle; in i2c_atr_add_adapter()
786 struct i2c_adapter *parent = atr->parent; in i2c_atr_add_adapter()
788 struct device *dev = atr->dev; in i2c_atr_add_adapter()
789 u32 chan_id = desc->chan_id; in i2c_atr_add_adapter()
793 if (chan_id >= atr->max_adapters) { in i2c_atr_add_adapter()
794 dev_err(dev, "No room for more i2c-atr adapters\n"); in i2c_atr_add_adapter()
795 return -EINVAL; in i2c_atr_add_adapter()
798 if (atr->adapter[chan_id]) { in i2c_atr_add_adapter()
800 return -EEXIST; in i2c_atr_add_adapter()
805 return -ENOMEM; in i2c_atr_add_adapter()
807 if (!desc->parent) in i2c_atr_add_adapter()
808 desc->parent = dev; in i2c_atr_add_adapter()
810 chan->atr = atr; in i2c_atr_add_adapter()
811 chan->chan_id = chan_id; in i2c_atr_add_adapter()
812 INIT_LIST_HEAD(&chan->alias_pairs); in i2c_atr_add_adapter()
813 lockdep_register_key(&chan->alias_pairs_lock_key); in i2c_atr_add_adapter()
814 lockdep_register_key(&chan->orig_addrs_lock_key); in i2c_atr_add_adapter()
815 mutex_init_with_key(&chan->alias_pairs_lock, &chan->alias_pairs_lock_key); in i2c_atr_add_adapter()
816 mutex_init_with_key(&chan->orig_addrs_lock, &chan->orig_addrs_lock_key); in i2c_atr_add_adapter()
818 snprintf(chan->adap.name, sizeof(chan->adap.name), "i2c-%d-atr-%d", in i2c_atr_add_adapter()
820 chan->adap.owner = THIS_MODULE; in i2c_atr_add_adapter()
821 chan->adap.algo = &atr->algo; in i2c_atr_add_adapter()
822 chan->adap.algo_data = chan; in i2c_atr_add_adapter()
823 chan->adap.dev.parent = desc->parent; in i2c_atr_add_adapter()
824 chan->adap.retries = parent->retries; in i2c_atr_add_adapter()
825 chan->adap.timeout = parent->timeout; in i2c_atr_add_adapter()
826 chan->adap.quirks = parent->quirks; in i2c_atr_add_adapter()
827 chan->adap.lock_ops = &i2c_atr_lock_ops; in i2c_atr_add_adapter()
830 device_set_node(&chan->adap.dev, fwnode_handle_get(bus_handle)); in i2c_atr_add_adapter()
836 atr_node = device_get_named_child_node(dev, "i2c-atr"); in i2c_atr_add_adapter()
846 device_set_node(&chan->adap.dev, child); in i2c_atr_add_adapter()
850 if (desc->num_aliases > 0) { in i2c_atr_add_adapter()
851 chan->alias_pool = i2c_atr_alloc_alias_pool(desc->num_aliases, false); in i2c_atr_add_adapter()
852 if (IS_ERR(chan->alias_pool)) { in i2c_atr_add_adapter()
853 ret = PTR_ERR(chan->alias_pool); in i2c_atr_add_adapter()
857 for (idx = 0; idx < desc->num_aliases; idx++) in i2c_atr_add_adapter()
858 chan->alias_pool->aliases[idx] = desc->aliases[idx]; in i2c_atr_add_adapter()
860 chan->alias_pool = atr->alias_pool; in i2c_atr_add_adapter()
863 atr->adapter[chan_id] = &chan->adap; in i2c_atr_add_adapter()
865 ret = i2c_add_adapter(&chan->adap); in i2c_atr_add_adapter()
867 dev_err(dev, "failed to add atr-adapter %u (error=%d)\n", in i2c_atr_add_adapter()
872 snprintf(symlink_name, sizeof(symlink_name), "channel-%u", in i2c_atr_add_adapter()
873 chan->chan_id); in i2c_atr_add_adapter()
875 ret = sysfs_create_link(&chan->adap.dev.kobj, &dev->kobj, "atr_device"); in i2c_atr_add_adapter()
878 ret = sysfs_create_link(&dev->kobj, &chan->adap.dev.kobj, symlink_name); in i2c_atr_add_adapter()
882 dev_dbg(dev, "Added ATR child bus %d\n", i2c_adapter_id(&chan->adap)); in i2c_atr_add_adapter()
887 if (!chan->alias_pool->shared) in i2c_atr_add_adapter()
888 i2c_atr_free_alias_pool(chan->alias_pool); in i2c_atr_add_adapter()
890 fwnode_handle_put(dev_fwnode(&chan->adap.dev)); in i2c_atr_add_adapter()
891 mutex_destroy(&chan->orig_addrs_lock); in i2c_atr_add_adapter()
892 mutex_destroy(&chan->alias_pairs_lock); in i2c_atr_add_adapter()
893 lockdep_unregister_key(&chan->orig_addrs_lock_key); in i2c_atr_add_adapter()
894 lockdep_unregister_key(&chan->alias_pairs_lock_key); in i2c_atr_add_adapter()
906 struct device *dev = atr->dev; in i2c_atr_del_adapter()
908 adap = atr->adapter[chan_id]; in i2c_atr_del_adapter()
912 chan = adap->algo_data; in i2c_atr_del_adapter()
913 fwnode = dev_fwnode(&adap->dev); in i2c_atr_del_adapter()
917 snprintf(symlink_name, sizeof(symlink_name), "channel-%u", in i2c_atr_del_adapter()
918 chan->chan_id); in i2c_atr_del_adapter()
919 sysfs_remove_link(&dev->kobj, symlink_name); in i2c_atr_del_adapter()
920 sysfs_remove_link(&chan->adap.dev.kobj, "atr_device"); in i2c_atr_del_adapter()
924 if (!chan->alias_pool->shared) in i2c_atr_del_adapter()
925 i2c_atr_free_alias_pool(chan->alias_pool); in i2c_atr_del_adapter()
927 atr->adapter[chan_id] = NULL; in i2c_atr_del_adapter()
930 mutex_destroy(&chan->orig_addrs_lock); in i2c_atr_del_adapter()
931 mutex_destroy(&chan->alias_pairs_lock); in i2c_atr_del_adapter()
932 lockdep_unregister_key(&chan->orig_addrs_lock_key); in i2c_atr_del_adapter()
933 lockdep_unregister_key(&chan->alias_pairs_lock_key); in i2c_atr_del_adapter()
934 kfree(chan->orig_addrs); in i2c_atr_del_adapter()
941 atr->priv = data; in i2c_atr_set_driver_data()
947 return atr->priv; in i2c_atr_get_driver_data()