cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

i2c-mux.c (12767B)


      1/*
      2 * Multiplexed I2C bus driver.
      3 *
      4 * Copyright (c) 2008-2009 Rodolfo Giometti <giometti@linux.it>
      5 * Copyright (c) 2008-2009 Eurotech S.p.A. <info@eurotech.it>
      6 * Copyright (c) 2009-2010 NSN GmbH & Co KG <michael.lawnick.ext@nsn.com>
      7 *
      8 * Simplifies access to complex multiplexed I2C bus topologies, by presenting
      9 * each multiplexed bus segment as an additional I2C adapter.
     10 * Supports multi-level mux'ing (mux behind a mux).
     11 *
     12 * Based on:
     13 *	i2c-virt.c from Kumar Gala <galak@kernel.crashing.org>
     14 *	i2c-virtual.c from Ken Harrenstien, Copyright (c) 2004 Google, Inc.
     15 *	i2c-virtual.c from Brian Kuschak <bkuschak@yahoo.com>
     16 *
     17 * This file is licensed under the terms of the GNU General Public
     18 * License version 2. This program is licensed "as is" without any
     19 * warranty of any kind, whether express or implied.
     20 */
     21
     22#include <linux/acpi.h>
     23#include <linux/i2c.h>
     24#include <linux/i2c-mux.h>
     25#include <linux/kernel.h>
     26#include <linux/module.h>
     27#include <linux/of.h>
     28#include <linux/slab.h>
     29#include <linux/sysfs.h>
     30
     31/* multiplexer per channel data */
     32struct i2c_mux_priv {
     33	struct i2c_adapter adap;
     34	struct i2c_algorithm algo;
     35	struct i2c_mux_core *muxc;
     36	u32 chan_id;
     37};
     38
     39static int __i2c_mux_master_xfer(struct i2c_adapter *adap,
     40				 struct i2c_msg msgs[], int num)
     41{
     42	struct i2c_mux_priv *priv = adap->algo_data;
     43	struct i2c_mux_core *muxc = priv->muxc;
     44	struct i2c_adapter *parent = muxc->parent;
     45	int ret;
     46
     47	/* Switch to the right mux port and perform the transfer. */
     48
     49	ret = muxc->select(muxc, priv->chan_id);
     50	if (ret >= 0)
     51		ret = __i2c_transfer(parent, msgs, num);
     52	if (muxc->deselect)
     53		muxc->deselect(muxc, priv->chan_id);
     54
     55	return ret;
     56}
     57
     58static int i2c_mux_master_xfer(struct i2c_adapter *adap,
     59			       struct i2c_msg msgs[], int num)
     60{
     61	struct i2c_mux_priv *priv = adap->algo_data;
     62	struct i2c_mux_core *muxc = priv->muxc;
     63	struct i2c_adapter *parent = muxc->parent;
     64	int ret;
     65
     66	/* Switch to the right mux port and perform the transfer. */
     67
     68	ret = muxc->select(muxc, priv->chan_id);
     69	if (ret >= 0)
     70		ret = i2c_transfer(parent, msgs, num);
     71	if (muxc->deselect)
     72		muxc->deselect(muxc, priv->chan_id);
     73
     74	return ret;
     75}
     76
     77static int __i2c_mux_smbus_xfer(struct i2c_adapter *adap,
     78				u16 addr, unsigned short flags,
     79				char read_write, u8 command,
     80				int size, union i2c_smbus_data *data)
     81{
     82	struct i2c_mux_priv *priv = adap->algo_data;
     83	struct i2c_mux_core *muxc = priv->muxc;
     84	struct i2c_adapter *parent = muxc->parent;
     85	int ret;
     86
     87	/* Select the right mux port and perform the transfer. */
     88
     89	ret = muxc->select(muxc, priv->chan_id);
     90	if (ret >= 0)
     91		ret = __i2c_smbus_xfer(parent, addr, flags,
     92				       read_write, command, size, data);
     93	if (muxc->deselect)
     94		muxc->deselect(muxc, priv->chan_id);
     95
     96	return ret;
     97}
     98
     99static int i2c_mux_smbus_xfer(struct i2c_adapter *adap,
    100			      u16 addr, unsigned short flags,
    101			      char read_write, u8 command,
    102			      int size, union i2c_smbus_data *data)
    103{
    104	struct i2c_mux_priv *priv = adap->algo_data;
    105	struct i2c_mux_core *muxc = priv->muxc;
    106	struct i2c_adapter *parent = muxc->parent;
    107	int ret;
    108
    109	/* Select the right mux port and perform the transfer. */
    110
    111	ret = muxc->select(muxc, priv->chan_id);
    112	if (ret >= 0)
    113		ret = i2c_smbus_xfer(parent, addr, flags,
    114				     read_write, command, size, data);
    115	if (muxc->deselect)
    116		muxc->deselect(muxc, priv->chan_id);
    117
    118	return ret;
    119}
    120
    121/* Return the parent's functionality */
    122static u32 i2c_mux_functionality(struct i2c_adapter *adap)
    123{
    124	struct i2c_mux_priv *priv = adap->algo_data;
    125	struct i2c_adapter *parent = priv->muxc->parent;
    126
    127	return parent->algo->functionality(parent);
    128}
    129
    130/* Return all parent classes, merged */
    131static unsigned int i2c_mux_parent_classes(struct i2c_adapter *parent)
    132{
    133	unsigned int class = 0;
    134
    135	do {
    136		class |= parent->class;
    137		parent = i2c_parent_is_i2c_adapter(parent);
    138	} while (parent);
    139
    140	return class;
    141}
    142
    143static void i2c_mux_lock_bus(struct i2c_adapter *adapter, unsigned int flags)
    144{
    145	struct i2c_mux_priv *priv = adapter->algo_data;
    146	struct i2c_adapter *parent = priv->muxc->parent;
    147
    148	rt_mutex_lock_nested(&parent->mux_lock, i2c_adapter_depth(adapter));
    149	if (!(flags & I2C_LOCK_ROOT_ADAPTER))
    150		return;
    151	i2c_lock_bus(parent, flags);
    152}
    153
    154static int i2c_mux_trylock_bus(struct i2c_adapter *adapter, unsigned int flags)
    155{
    156	struct i2c_mux_priv *priv = adapter->algo_data;
    157	struct i2c_adapter *parent = priv->muxc->parent;
    158
    159	if (!rt_mutex_trylock(&parent->mux_lock))
    160		return 0;	/* mux_lock not locked, failure */
    161	if (!(flags & I2C_LOCK_ROOT_ADAPTER))
    162		return 1;	/* we only want mux_lock, success */
    163	if (i2c_trylock_bus(parent, flags))
    164		return 1;	/* parent locked too, success */
    165	rt_mutex_unlock(&parent->mux_lock);
    166	return 0;		/* parent not locked, failure */
    167}
    168
    169static void i2c_mux_unlock_bus(struct i2c_adapter *adapter, unsigned int flags)
    170{
    171	struct i2c_mux_priv *priv = adapter->algo_data;
    172	struct i2c_adapter *parent = priv->muxc->parent;
    173
    174	if (flags & I2C_LOCK_ROOT_ADAPTER)
    175		i2c_unlock_bus(parent, flags);
    176	rt_mutex_unlock(&parent->mux_lock);
    177}
    178
    179static void i2c_parent_lock_bus(struct i2c_adapter *adapter,
    180				unsigned int flags)
    181{
    182	struct i2c_mux_priv *priv = adapter->algo_data;
    183	struct i2c_adapter *parent = priv->muxc->parent;
    184
    185	rt_mutex_lock_nested(&parent->mux_lock, i2c_adapter_depth(adapter));
    186	i2c_lock_bus(parent, flags);
    187}
    188
    189static int i2c_parent_trylock_bus(struct i2c_adapter *adapter,
    190				  unsigned int flags)
    191{
    192	struct i2c_mux_priv *priv = adapter->algo_data;
    193	struct i2c_adapter *parent = priv->muxc->parent;
    194
    195	if (!rt_mutex_trylock(&parent->mux_lock))
    196		return 0;	/* mux_lock not locked, failure */
    197	if (i2c_trylock_bus(parent, flags))
    198		return 1;	/* parent locked too, success */
    199	rt_mutex_unlock(&parent->mux_lock);
    200	return 0;		/* parent not locked, failure */
    201}
    202
    203static void i2c_parent_unlock_bus(struct i2c_adapter *adapter,
    204				  unsigned int flags)
    205{
    206	struct i2c_mux_priv *priv = adapter->algo_data;
    207	struct i2c_adapter *parent = priv->muxc->parent;
    208
    209	i2c_unlock_bus(parent, flags);
    210	rt_mutex_unlock(&parent->mux_lock);
    211}
    212
    213struct i2c_adapter *i2c_root_adapter(struct device *dev)
    214{
    215	struct device *i2c;
    216	struct i2c_adapter *i2c_root;
    217
    218	/*
    219	 * Walk up the device tree to find an i2c adapter, indicating
    220	 * that this is an i2c client device. Check all ancestors to
    221	 * handle mfd devices etc.
    222	 */
    223	for (i2c = dev; i2c; i2c = i2c->parent) {
    224		if (i2c->type == &i2c_adapter_type)
    225			break;
    226	}
    227	if (!i2c)
    228		return NULL;
    229
    230	/* Continue up the tree to find the root i2c adapter */
    231	i2c_root = to_i2c_adapter(i2c);
    232	while (i2c_parent_is_i2c_adapter(i2c_root))
    233		i2c_root = i2c_parent_is_i2c_adapter(i2c_root);
    234
    235	return i2c_root;
    236}
    237EXPORT_SYMBOL_GPL(i2c_root_adapter);
    238
    239struct i2c_mux_core *i2c_mux_alloc(struct i2c_adapter *parent,
    240				   struct device *dev, int max_adapters,
    241				   int sizeof_priv, u32 flags,
    242				   int (*select)(struct i2c_mux_core *, u32),
    243				   int (*deselect)(struct i2c_mux_core *, u32))
    244{
    245	struct i2c_mux_core *muxc;
    246
    247	muxc = devm_kzalloc(dev, struct_size(muxc, adapter, max_adapters)
    248			    + sizeof_priv, GFP_KERNEL);
    249	if (!muxc)
    250		return NULL;
    251	if (sizeof_priv)
    252		muxc->priv = &muxc->adapter[max_adapters];
    253
    254	muxc->parent = parent;
    255	muxc->dev = dev;
    256	if (flags & I2C_MUX_LOCKED)
    257		muxc->mux_locked = true;
    258	if (flags & I2C_MUX_ARBITRATOR)
    259		muxc->arbitrator = true;
    260	if (flags & I2C_MUX_GATE)
    261		muxc->gate = true;
    262	muxc->select = select;
    263	muxc->deselect = deselect;
    264	muxc->max_adapters = max_adapters;
    265
    266	return muxc;
    267}
    268EXPORT_SYMBOL_GPL(i2c_mux_alloc);
    269
    270static const struct i2c_lock_operations i2c_mux_lock_ops = {
    271	.lock_bus =    i2c_mux_lock_bus,
    272	.trylock_bus = i2c_mux_trylock_bus,
    273	.unlock_bus =  i2c_mux_unlock_bus,
    274};
    275
    276static const struct i2c_lock_operations i2c_parent_lock_ops = {
    277	.lock_bus =    i2c_parent_lock_bus,
    278	.trylock_bus = i2c_parent_trylock_bus,
    279	.unlock_bus =  i2c_parent_unlock_bus,
    280};
    281
    282int i2c_mux_add_adapter(struct i2c_mux_core *muxc,
    283			u32 force_nr, u32 chan_id,
    284			unsigned int class)
    285{
    286	struct i2c_adapter *parent = muxc->parent;
    287	struct i2c_mux_priv *priv;
    288	char symlink_name[20];
    289	int ret;
    290
    291	if (muxc->num_adapters >= muxc->max_adapters) {
    292		dev_err(muxc->dev, "No room for more i2c-mux adapters\n");
    293		return -EINVAL;
    294	}
    295
    296	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
    297	if (!priv)
    298		return -ENOMEM;
    299
    300	/* Set up private adapter data */
    301	priv->muxc = muxc;
    302	priv->chan_id = chan_id;
    303
    304	/* Need to do algo dynamically because we don't know ahead
    305	 * of time what sort of physical adapter we'll be dealing with.
    306	 */
    307	if (parent->algo->master_xfer) {
    308		if (muxc->mux_locked)
    309			priv->algo.master_xfer = i2c_mux_master_xfer;
    310		else
    311			priv->algo.master_xfer = __i2c_mux_master_xfer;
    312	}
    313	if (parent->algo->master_xfer_atomic)
    314		priv->algo.master_xfer_atomic = priv->algo.master_xfer;
    315
    316	if (parent->algo->smbus_xfer) {
    317		if (muxc->mux_locked)
    318			priv->algo.smbus_xfer = i2c_mux_smbus_xfer;
    319		else
    320			priv->algo.smbus_xfer = __i2c_mux_smbus_xfer;
    321	}
    322	if (parent->algo->smbus_xfer_atomic)
    323		priv->algo.smbus_xfer_atomic = priv->algo.smbus_xfer;
    324
    325	priv->algo.functionality = i2c_mux_functionality;
    326
    327	/* Now fill out new adapter structure */
    328	snprintf(priv->adap.name, sizeof(priv->adap.name),
    329		 "i2c-%d-mux (chan_id %d)", i2c_adapter_id(parent), chan_id);
    330	priv->adap.owner = THIS_MODULE;
    331	priv->adap.algo = &priv->algo;
    332	priv->adap.algo_data = priv;
    333	priv->adap.dev.parent = &parent->dev;
    334	priv->adap.retries = parent->retries;
    335	priv->adap.timeout = parent->timeout;
    336	priv->adap.quirks = parent->quirks;
    337	if (muxc->mux_locked)
    338		priv->adap.lock_ops = &i2c_mux_lock_ops;
    339	else
    340		priv->adap.lock_ops = &i2c_parent_lock_ops;
    341
    342	/* Sanity check on class */
    343	if (i2c_mux_parent_classes(parent) & class)
    344		dev_err(&parent->dev,
    345			"Segment %d behind mux can't share classes with ancestors\n",
    346			chan_id);
    347	else
    348		priv->adap.class = class;
    349
    350	/*
    351	 * Try to populate the mux adapter's of_node, expands to
    352	 * nothing if !CONFIG_OF.
    353	 */
    354	if (muxc->dev->of_node) {
    355		struct device_node *dev_node = muxc->dev->of_node;
    356		struct device_node *mux_node, *child = NULL;
    357		u32 reg;
    358
    359		if (muxc->arbitrator)
    360			mux_node = of_get_child_by_name(dev_node, "i2c-arb");
    361		else if (muxc->gate)
    362			mux_node = of_get_child_by_name(dev_node, "i2c-gate");
    363		else
    364			mux_node = of_get_child_by_name(dev_node, "i2c-mux");
    365
    366		if (mux_node) {
    367			/* A "reg" property indicates an old-style DT entry */
    368			if (!of_property_read_u32(mux_node, "reg", &reg)) {
    369				of_node_put(mux_node);
    370				mux_node = NULL;
    371			}
    372		}
    373
    374		if (!mux_node)
    375			mux_node = of_node_get(dev_node);
    376		else if (muxc->arbitrator || muxc->gate)
    377			child = of_node_get(mux_node);
    378
    379		if (!child) {
    380			for_each_child_of_node(mux_node, child) {
    381				ret = of_property_read_u32(child, "reg", &reg);
    382				if (ret)
    383					continue;
    384				if (chan_id == reg)
    385					break;
    386			}
    387		}
    388
    389		priv->adap.dev.of_node = child;
    390		of_node_put(mux_node);
    391	}
    392
    393	/*
    394	 * Associate the mux channel with an ACPI node.
    395	 */
    396	if (has_acpi_companion(muxc->dev))
    397		acpi_preset_companion(&priv->adap.dev,
    398				      ACPI_COMPANION(muxc->dev),
    399				      chan_id);
    400
    401	if (force_nr) {
    402		priv->adap.nr = force_nr;
    403		ret = i2c_add_numbered_adapter(&priv->adap);
    404		if (ret < 0) {
    405			dev_err(&parent->dev,
    406				"failed to add mux-adapter %u as bus %u (error=%d)\n",
    407				chan_id, force_nr, ret);
    408			goto err_free_priv;
    409		}
    410	} else {
    411		ret = i2c_add_adapter(&priv->adap);
    412		if (ret < 0) {
    413			dev_err(&parent->dev,
    414				"failed to add mux-adapter %u (error=%d)\n",
    415				chan_id, ret);
    416			goto err_free_priv;
    417		}
    418	}
    419
    420	WARN(sysfs_create_link(&priv->adap.dev.kobj, &muxc->dev->kobj,
    421			       "mux_device"),
    422	     "can't create symlink to mux device\n");
    423
    424	snprintf(symlink_name, sizeof(symlink_name), "channel-%u", chan_id);
    425	WARN(sysfs_create_link(&muxc->dev->kobj, &priv->adap.dev.kobj,
    426			       symlink_name),
    427	     "can't create symlink to channel %u\n", chan_id);
    428	dev_info(&parent->dev, "Added multiplexed i2c bus %d\n",
    429		 i2c_adapter_id(&priv->adap));
    430
    431	muxc->adapter[muxc->num_adapters++] = &priv->adap;
    432	return 0;
    433
    434err_free_priv:
    435	kfree(priv);
    436	return ret;
    437}
    438EXPORT_SYMBOL_GPL(i2c_mux_add_adapter);
    439
    440void i2c_mux_del_adapters(struct i2c_mux_core *muxc)
    441{
    442	char symlink_name[20];
    443
    444	while (muxc->num_adapters) {
    445		struct i2c_adapter *adap = muxc->adapter[--muxc->num_adapters];
    446		struct i2c_mux_priv *priv = adap->algo_data;
    447		struct device_node *np = adap->dev.of_node;
    448
    449		muxc->adapter[muxc->num_adapters] = NULL;
    450
    451		snprintf(symlink_name, sizeof(symlink_name),
    452			 "channel-%u", priv->chan_id);
    453		sysfs_remove_link(&muxc->dev->kobj, symlink_name);
    454
    455		sysfs_remove_link(&priv->adap.dev.kobj, "mux_device");
    456		i2c_del_adapter(adap);
    457		of_node_put(np);
    458		kfree(priv);
    459	}
    460}
    461EXPORT_SYMBOL_GPL(i2c_mux_del_adapters);
    462
    463MODULE_AUTHOR("Rodolfo Giometti <giometti@linux.it>");
    464MODULE_DESCRIPTION("I2C driver for multiplexed I2C busses");
    465MODULE_LICENSE("GPL v2");