162306a36Sopenharmony_ci/*
262306a36Sopenharmony_ci * I2C multiplexer driver for PCA9541 bus master selector
362306a36Sopenharmony_ci *
462306a36Sopenharmony_ci * Copyright (c) 2010 Ericsson AB.
562306a36Sopenharmony_ci *
662306a36Sopenharmony_ci * Author: Guenter Roeck <linux@roeck-us.net>
762306a36Sopenharmony_ci *
862306a36Sopenharmony_ci * Derived from:
962306a36Sopenharmony_ci *  pca954x.c
1062306a36Sopenharmony_ci *
1162306a36Sopenharmony_ci *  Copyright (c) 2008-2009 Rodolfo Giometti <giometti@linux.it>
1262306a36Sopenharmony_ci *  Copyright (c) 2008-2009 Eurotech S.p.A. <info@eurotech.it>
1362306a36Sopenharmony_ci *
1462306a36Sopenharmony_ci * This file is licensed under the terms of the GNU General Public
1562306a36Sopenharmony_ci * License version 2. This program is licensed "as is" without any
1662306a36Sopenharmony_ci * warranty of any kind, whether express or implied.
1762306a36Sopenharmony_ci */
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_ci#include <linux/bitops.h>
2062306a36Sopenharmony_ci#include <linux/delay.h>
2162306a36Sopenharmony_ci#include <linux/device.h>
2262306a36Sopenharmony_ci#include <linux/i2c.h>
2362306a36Sopenharmony_ci#include <linux/i2c-mux.h>
2462306a36Sopenharmony_ci#include <linux/jiffies.h>
2562306a36Sopenharmony_ci#include <linux/module.h>
2662306a36Sopenharmony_ci#include <linux/slab.h>
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_ci/*
2962306a36Sopenharmony_ci * The PCA9541 is a bus master selector. It supports two I2C masters connected
3062306a36Sopenharmony_ci * to a single slave bus.
3162306a36Sopenharmony_ci *
3262306a36Sopenharmony_ci * Before each bus transaction, a master has to acquire bus ownership. After the
3362306a36Sopenharmony_ci * transaction is complete, bus ownership has to be released. This fits well
3462306a36Sopenharmony_ci * into the I2C multiplexer framework, which provides select and release
3562306a36Sopenharmony_ci * functions for this purpose. For this reason, this driver is modeled as
3662306a36Sopenharmony_ci * single-channel I2C bus multiplexer.
3762306a36Sopenharmony_ci *
3862306a36Sopenharmony_ci * This driver assumes that the two bus masters are controlled by two different
3962306a36Sopenharmony_ci * hosts. If a single host controls both masters, platform code has to ensure
4062306a36Sopenharmony_ci * that only one of the masters is instantiated at any given time.
4162306a36Sopenharmony_ci */
4262306a36Sopenharmony_ci
4362306a36Sopenharmony_ci#define PCA9541_CONTROL		0x01
4462306a36Sopenharmony_ci#define PCA9541_ISTAT		0x02
4562306a36Sopenharmony_ci
4662306a36Sopenharmony_ci#define PCA9541_CTL_MYBUS	BIT(0)
4762306a36Sopenharmony_ci#define PCA9541_CTL_NMYBUS	BIT(1)
4862306a36Sopenharmony_ci#define PCA9541_CTL_BUSON	BIT(2)
4962306a36Sopenharmony_ci#define PCA9541_CTL_NBUSON	BIT(3)
5062306a36Sopenharmony_ci#define PCA9541_CTL_BUSINIT	BIT(4)
5162306a36Sopenharmony_ci#define PCA9541_CTL_TESTON	BIT(6)
5262306a36Sopenharmony_ci#define PCA9541_CTL_NTESTON	BIT(7)
5362306a36Sopenharmony_ci
5462306a36Sopenharmony_ci#define PCA9541_ISTAT_INTIN	BIT(0)
5562306a36Sopenharmony_ci#define PCA9541_ISTAT_BUSINIT	BIT(1)
5662306a36Sopenharmony_ci#define PCA9541_ISTAT_BUSOK	BIT(2)
5762306a36Sopenharmony_ci#define PCA9541_ISTAT_BUSLOST	BIT(3)
5862306a36Sopenharmony_ci#define PCA9541_ISTAT_MYTEST	BIT(6)
5962306a36Sopenharmony_ci#define PCA9541_ISTAT_NMYTEST	BIT(7)
6062306a36Sopenharmony_ci
6162306a36Sopenharmony_ci#define BUSON		(PCA9541_CTL_BUSON | PCA9541_CTL_NBUSON)
6262306a36Sopenharmony_ci#define MYBUS		(PCA9541_CTL_MYBUS | PCA9541_CTL_NMYBUS)
6362306a36Sopenharmony_ci#define mybus(x)	(!((x) & MYBUS) || ((x) & MYBUS) == MYBUS)
6462306a36Sopenharmony_ci#define busoff(x)	(!((x) & BUSON) || ((x) & BUSON) == BUSON)
6562306a36Sopenharmony_ci
6662306a36Sopenharmony_ci/* arbitration timeouts, in jiffies */
6762306a36Sopenharmony_ci#define ARB_TIMEOUT	(HZ / 8)	/* 125 ms until forcing bus ownership */
6862306a36Sopenharmony_ci#define ARB2_TIMEOUT	(HZ / 4)	/* 250 ms until acquisition failure */
6962306a36Sopenharmony_ci
7062306a36Sopenharmony_ci/* arbitration retry delays, in us */
7162306a36Sopenharmony_ci#define SELECT_DELAY_SHORT	50
7262306a36Sopenharmony_ci#define SELECT_DELAY_LONG	1000
7362306a36Sopenharmony_ci
7462306a36Sopenharmony_cistruct pca9541 {
7562306a36Sopenharmony_ci	struct i2c_client *client;
7662306a36Sopenharmony_ci	unsigned long select_timeout;
7762306a36Sopenharmony_ci	unsigned long arb_timeout;
7862306a36Sopenharmony_ci};
7962306a36Sopenharmony_ci
8062306a36Sopenharmony_cistatic const struct i2c_device_id pca9541_id[] = {
8162306a36Sopenharmony_ci	{"pca9541", 0},
8262306a36Sopenharmony_ci	{}
8362306a36Sopenharmony_ci};
8462306a36Sopenharmony_ci
8562306a36Sopenharmony_ciMODULE_DEVICE_TABLE(i2c, pca9541_id);
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_ci#ifdef CONFIG_OF
8862306a36Sopenharmony_cistatic const struct of_device_id pca9541_of_match[] = {
8962306a36Sopenharmony_ci	{ .compatible = "nxp,pca9541" },
9062306a36Sopenharmony_ci	{}
9162306a36Sopenharmony_ci};
9262306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, pca9541_of_match);
9362306a36Sopenharmony_ci#endif
9462306a36Sopenharmony_ci
9562306a36Sopenharmony_ci/*
9662306a36Sopenharmony_ci * Write to chip register. Don't use i2c_transfer()/i2c_smbus_xfer()
9762306a36Sopenharmony_ci * as they will try to lock the adapter a second time.
9862306a36Sopenharmony_ci */
9962306a36Sopenharmony_cistatic int pca9541_reg_write(struct i2c_client *client, u8 command, u8 val)
10062306a36Sopenharmony_ci{
10162306a36Sopenharmony_ci	struct i2c_adapter *adap = client->adapter;
10262306a36Sopenharmony_ci	union i2c_smbus_data data = { .byte = val };
10362306a36Sopenharmony_ci
10462306a36Sopenharmony_ci	return __i2c_smbus_xfer(adap, client->addr, client->flags,
10562306a36Sopenharmony_ci				I2C_SMBUS_WRITE, command,
10662306a36Sopenharmony_ci				I2C_SMBUS_BYTE_DATA, &data);
10762306a36Sopenharmony_ci}
10862306a36Sopenharmony_ci
10962306a36Sopenharmony_ci/*
11062306a36Sopenharmony_ci * Read from chip register. Don't use i2c_transfer()/i2c_smbus_xfer()
11162306a36Sopenharmony_ci * as they will try to lock adapter a second time.
11262306a36Sopenharmony_ci */
11362306a36Sopenharmony_cistatic int pca9541_reg_read(struct i2c_client *client, u8 command)
11462306a36Sopenharmony_ci{
11562306a36Sopenharmony_ci	struct i2c_adapter *adap = client->adapter;
11662306a36Sopenharmony_ci	union i2c_smbus_data data;
11762306a36Sopenharmony_ci	int ret;
11862306a36Sopenharmony_ci
11962306a36Sopenharmony_ci	ret = __i2c_smbus_xfer(adap, client->addr, client->flags,
12062306a36Sopenharmony_ci			       I2C_SMBUS_READ, command,
12162306a36Sopenharmony_ci			       I2C_SMBUS_BYTE_DATA, &data);
12262306a36Sopenharmony_ci
12362306a36Sopenharmony_ci	return ret ?: data.byte;
12462306a36Sopenharmony_ci}
12562306a36Sopenharmony_ci
12662306a36Sopenharmony_ci/*
12762306a36Sopenharmony_ci * Arbitration management functions
12862306a36Sopenharmony_ci */
12962306a36Sopenharmony_ci
13062306a36Sopenharmony_ci/* Release bus. Also reset NTESTON and BUSINIT if it was set. */
13162306a36Sopenharmony_cistatic void pca9541_release_bus(struct i2c_client *client)
13262306a36Sopenharmony_ci{
13362306a36Sopenharmony_ci	int reg;
13462306a36Sopenharmony_ci
13562306a36Sopenharmony_ci	reg = pca9541_reg_read(client, PCA9541_CONTROL);
13662306a36Sopenharmony_ci	if (reg >= 0 && !busoff(reg) && mybus(reg))
13762306a36Sopenharmony_ci		pca9541_reg_write(client, PCA9541_CONTROL,
13862306a36Sopenharmony_ci				  (reg & PCA9541_CTL_NBUSON) >> 1);
13962306a36Sopenharmony_ci}
14062306a36Sopenharmony_ci
14162306a36Sopenharmony_ci/*
14262306a36Sopenharmony_ci * Arbitration is defined as a two-step process. A bus master can only activate
14362306a36Sopenharmony_ci * the slave bus if it owns it; otherwise it has to request ownership first.
14462306a36Sopenharmony_ci * This multi-step process ensures that access contention is resolved
14562306a36Sopenharmony_ci * gracefully.
14662306a36Sopenharmony_ci *
14762306a36Sopenharmony_ci * Bus	Ownership	Other master	Action
14862306a36Sopenharmony_ci * state		requested access
14962306a36Sopenharmony_ci * ----------------------------------------------------
15062306a36Sopenharmony_ci * off	-		yes		wait for arbitration timeout or
15162306a36Sopenharmony_ci *					for other master to drop request
15262306a36Sopenharmony_ci * off	no		no		take ownership
15362306a36Sopenharmony_ci * off	yes		no		turn on bus
15462306a36Sopenharmony_ci * on	yes		-		done
15562306a36Sopenharmony_ci * on	no		-		wait for arbitration timeout or
15662306a36Sopenharmony_ci *					for other master to release bus
15762306a36Sopenharmony_ci *
15862306a36Sopenharmony_ci * The main contention point occurs if the slave bus is off and both masters
15962306a36Sopenharmony_ci * request ownership at the same time. In this case, one master will turn on
16062306a36Sopenharmony_ci * the slave bus, believing that it owns it. The other master will request
16162306a36Sopenharmony_ci * bus ownership. Result is that the bus is turned on, and master which did
16262306a36Sopenharmony_ci * _not_ own the slave bus before ends up owning it.
16362306a36Sopenharmony_ci */
16462306a36Sopenharmony_ci
16562306a36Sopenharmony_ci/* Control commands per PCA9541 datasheet */
16662306a36Sopenharmony_cistatic const u8 pca9541_control[16] = {
16762306a36Sopenharmony_ci	4, 0, 1, 5, 4, 4, 5, 5, 0, 0, 1, 1, 0, 4, 5, 1
16862306a36Sopenharmony_ci};
16962306a36Sopenharmony_ci
17062306a36Sopenharmony_ci/*
17162306a36Sopenharmony_ci * Channel arbitration
17262306a36Sopenharmony_ci *
17362306a36Sopenharmony_ci * Return values:
17462306a36Sopenharmony_ci *  <0: error
17562306a36Sopenharmony_ci *  0 : bus not acquired
17662306a36Sopenharmony_ci *  1 : bus acquired
17762306a36Sopenharmony_ci */
17862306a36Sopenharmony_cistatic int pca9541_arbitrate(struct i2c_client *client)
17962306a36Sopenharmony_ci{
18062306a36Sopenharmony_ci	struct i2c_mux_core *muxc = i2c_get_clientdata(client);
18162306a36Sopenharmony_ci	struct pca9541 *data = i2c_mux_priv(muxc);
18262306a36Sopenharmony_ci	int reg;
18362306a36Sopenharmony_ci
18462306a36Sopenharmony_ci	reg = pca9541_reg_read(client, PCA9541_CONTROL);
18562306a36Sopenharmony_ci	if (reg < 0)
18662306a36Sopenharmony_ci		return reg;
18762306a36Sopenharmony_ci
18862306a36Sopenharmony_ci	if (busoff(reg)) {
18962306a36Sopenharmony_ci		int istat;
19062306a36Sopenharmony_ci		/*
19162306a36Sopenharmony_ci		 * Bus is off. Request ownership or turn it on unless
19262306a36Sopenharmony_ci		 * other master requested ownership.
19362306a36Sopenharmony_ci		 */
19462306a36Sopenharmony_ci		istat = pca9541_reg_read(client, PCA9541_ISTAT);
19562306a36Sopenharmony_ci		if (!(istat & PCA9541_ISTAT_NMYTEST)
19662306a36Sopenharmony_ci		    || time_is_before_eq_jiffies(data->arb_timeout)) {
19762306a36Sopenharmony_ci			/*
19862306a36Sopenharmony_ci			 * Other master did not request ownership,
19962306a36Sopenharmony_ci			 * or arbitration timeout expired. Take the bus.
20062306a36Sopenharmony_ci			 */
20162306a36Sopenharmony_ci			pca9541_reg_write(client,
20262306a36Sopenharmony_ci					  PCA9541_CONTROL,
20362306a36Sopenharmony_ci					  pca9541_control[reg & 0x0f]
20462306a36Sopenharmony_ci					  | PCA9541_CTL_NTESTON);
20562306a36Sopenharmony_ci			data->select_timeout = SELECT_DELAY_SHORT;
20662306a36Sopenharmony_ci		} else {
20762306a36Sopenharmony_ci			/*
20862306a36Sopenharmony_ci			 * Other master requested ownership.
20962306a36Sopenharmony_ci			 * Set extra long timeout to give it time to acquire it.
21062306a36Sopenharmony_ci			 */
21162306a36Sopenharmony_ci			data->select_timeout = SELECT_DELAY_LONG * 2;
21262306a36Sopenharmony_ci		}
21362306a36Sopenharmony_ci	} else if (mybus(reg)) {
21462306a36Sopenharmony_ci		/*
21562306a36Sopenharmony_ci		 * Bus is on, and we own it. We are done with acquisition.
21662306a36Sopenharmony_ci		 * Reset NTESTON and BUSINIT, then return success.
21762306a36Sopenharmony_ci		 */
21862306a36Sopenharmony_ci		if (reg & (PCA9541_CTL_NTESTON | PCA9541_CTL_BUSINIT))
21962306a36Sopenharmony_ci			pca9541_reg_write(client,
22062306a36Sopenharmony_ci					  PCA9541_CONTROL,
22162306a36Sopenharmony_ci					  reg & ~(PCA9541_CTL_NTESTON
22262306a36Sopenharmony_ci						  | PCA9541_CTL_BUSINIT));
22362306a36Sopenharmony_ci		return 1;
22462306a36Sopenharmony_ci	} else {
22562306a36Sopenharmony_ci		/*
22662306a36Sopenharmony_ci		 * Other master owns the bus.
22762306a36Sopenharmony_ci		 * If arbitration timeout has expired, force ownership.
22862306a36Sopenharmony_ci		 * Otherwise request it.
22962306a36Sopenharmony_ci		 */
23062306a36Sopenharmony_ci		data->select_timeout = SELECT_DELAY_LONG;
23162306a36Sopenharmony_ci		if (time_is_before_eq_jiffies(data->arb_timeout)) {
23262306a36Sopenharmony_ci			/* Time is up, take the bus and reset it. */
23362306a36Sopenharmony_ci			pca9541_reg_write(client,
23462306a36Sopenharmony_ci					  PCA9541_CONTROL,
23562306a36Sopenharmony_ci					  pca9541_control[reg & 0x0f]
23662306a36Sopenharmony_ci					  | PCA9541_CTL_BUSINIT
23762306a36Sopenharmony_ci					  | PCA9541_CTL_NTESTON);
23862306a36Sopenharmony_ci		} else {
23962306a36Sopenharmony_ci			/* Request bus ownership if needed */
24062306a36Sopenharmony_ci			if (!(reg & PCA9541_CTL_NTESTON))
24162306a36Sopenharmony_ci				pca9541_reg_write(client,
24262306a36Sopenharmony_ci						  PCA9541_CONTROL,
24362306a36Sopenharmony_ci						  reg | PCA9541_CTL_NTESTON);
24462306a36Sopenharmony_ci		}
24562306a36Sopenharmony_ci	}
24662306a36Sopenharmony_ci	return 0;
24762306a36Sopenharmony_ci}
24862306a36Sopenharmony_ci
24962306a36Sopenharmony_cistatic int pca9541_select_chan(struct i2c_mux_core *muxc, u32 chan)
25062306a36Sopenharmony_ci{
25162306a36Sopenharmony_ci	struct pca9541 *data = i2c_mux_priv(muxc);
25262306a36Sopenharmony_ci	struct i2c_client *client = data->client;
25362306a36Sopenharmony_ci	int ret;
25462306a36Sopenharmony_ci	unsigned long timeout = jiffies + ARB2_TIMEOUT;
25562306a36Sopenharmony_ci		/* give up after this time */
25662306a36Sopenharmony_ci
25762306a36Sopenharmony_ci	data->arb_timeout = jiffies + ARB_TIMEOUT;
25862306a36Sopenharmony_ci		/* force bus ownership after this time */
25962306a36Sopenharmony_ci
26062306a36Sopenharmony_ci	do {
26162306a36Sopenharmony_ci		ret = pca9541_arbitrate(client);
26262306a36Sopenharmony_ci		if (ret)
26362306a36Sopenharmony_ci			return ret < 0 ? ret : 0;
26462306a36Sopenharmony_ci
26562306a36Sopenharmony_ci		if (data->select_timeout == SELECT_DELAY_SHORT)
26662306a36Sopenharmony_ci			udelay(data->select_timeout);
26762306a36Sopenharmony_ci		else
26862306a36Sopenharmony_ci			msleep(data->select_timeout / 1000);
26962306a36Sopenharmony_ci	} while (time_is_after_eq_jiffies(timeout));
27062306a36Sopenharmony_ci
27162306a36Sopenharmony_ci	return -ETIMEDOUT;
27262306a36Sopenharmony_ci}
27362306a36Sopenharmony_ci
27462306a36Sopenharmony_cistatic int pca9541_release_chan(struct i2c_mux_core *muxc, u32 chan)
27562306a36Sopenharmony_ci{
27662306a36Sopenharmony_ci	struct pca9541 *data = i2c_mux_priv(muxc);
27762306a36Sopenharmony_ci	struct i2c_client *client = data->client;
27862306a36Sopenharmony_ci
27962306a36Sopenharmony_ci	pca9541_release_bus(client);
28062306a36Sopenharmony_ci	return 0;
28162306a36Sopenharmony_ci}
28262306a36Sopenharmony_ci
28362306a36Sopenharmony_ci/*
28462306a36Sopenharmony_ci * I2C init/probing/exit functions
28562306a36Sopenharmony_ci */
28662306a36Sopenharmony_cistatic int pca9541_probe(struct i2c_client *client)
28762306a36Sopenharmony_ci{
28862306a36Sopenharmony_ci	struct i2c_adapter *adap = client->adapter;
28962306a36Sopenharmony_ci	struct i2c_mux_core *muxc;
29062306a36Sopenharmony_ci	struct pca9541 *data;
29162306a36Sopenharmony_ci	int ret;
29262306a36Sopenharmony_ci
29362306a36Sopenharmony_ci	if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_BYTE_DATA))
29462306a36Sopenharmony_ci		return -ENODEV;
29562306a36Sopenharmony_ci
29662306a36Sopenharmony_ci	/*
29762306a36Sopenharmony_ci	 * I2C accesses are unprotected here.
29862306a36Sopenharmony_ci	 * We have to lock the I2C segment before releasing the bus.
29962306a36Sopenharmony_ci	 */
30062306a36Sopenharmony_ci	i2c_lock_bus(adap, I2C_LOCK_SEGMENT);
30162306a36Sopenharmony_ci	pca9541_release_bus(client);
30262306a36Sopenharmony_ci	i2c_unlock_bus(adap, I2C_LOCK_SEGMENT);
30362306a36Sopenharmony_ci
30462306a36Sopenharmony_ci	/* Create mux adapter */
30562306a36Sopenharmony_ci
30662306a36Sopenharmony_ci	muxc = i2c_mux_alloc(adap, &client->dev, 1, sizeof(*data),
30762306a36Sopenharmony_ci			     I2C_MUX_ARBITRATOR,
30862306a36Sopenharmony_ci			     pca9541_select_chan, pca9541_release_chan);
30962306a36Sopenharmony_ci	if (!muxc)
31062306a36Sopenharmony_ci		return -ENOMEM;
31162306a36Sopenharmony_ci
31262306a36Sopenharmony_ci	data = i2c_mux_priv(muxc);
31362306a36Sopenharmony_ci	data->client = client;
31462306a36Sopenharmony_ci
31562306a36Sopenharmony_ci	i2c_set_clientdata(client, muxc);
31662306a36Sopenharmony_ci
31762306a36Sopenharmony_ci	ret = i2c_mux_add_adapter(muxc, 0, 0, 0);
31862306a36Sopenharmony_ci	if (ret)
31962306a36Sopenharmony_ci		return ret;
32062306a36Sopenharmony_ci
32162306a36Sopenharmony_ci	dev_info(&client->dev, "registered master selector for I2C %s\n",
32262306a36Sopenharmony_ci		 client->name);
32362306a36Sopenharmony_ci
32462306a36Sopenharmony_ci	return 0;
32562306a36Sopenharmony_ci}
32662306a36Sopenharmony_ci
32762306a36Sopenharmony_cistatic void pca9541_remove(struct i2c_client *client)
32862306a36Sopenharmony_ci{
32962306a36Sopenharmony_ci	struct i2c_mux_core *muxc = i2c_get_clientdata(client);
33062306a36Sopenharmony_ci
33162306a36Sopenharmony_ci	i2c_mux_del_adapters(muxc);
33262306a36Sopenharmony_ci}
33362306a36Sopenharmony_ci
33462306a36Sopenharmony_cistatic struct i2c_driver pca9541_driver = {
33562306a36Sopenharmony_ci	.driver = {
33662306a36Sopenharmony_ci		   .name = "pca9541",
33762306a36Sopenharmony_ci		   .of_match_table = of_match_ptr(pca9541_of_match),
33862306a36Sopenharmony_ci		   },
33962306a36Sopenharmony_ci	.probe = pca9541_probe,
34062306a36Sopenharmony_ci	.remove = pca9541_remove,
34162306a36Sopenharmony_ci	.id_table = pca9541_id,
34262306a36Sopenharmony_ci};
34362306a36Sopenharmony_ci
34462306a36Sopenharmony_cimodule_i2c_driver(pca9541_driver);
34562306a36Sopenharmony_ci
34662306a36Sopenharmony_ciMODULE_AUTHOR("Guenter Roeck <linux@roeck-us.net>");
34762306a36Sopenharmony_ciMODULE_DESCRIPTION("PCA9541 I2C master selector driver");
34862306a36Sopenharmony_ciMODULE_LICENSE("GPL v2");
349