diff options
Diffstat (limited to 'drivers/i2c')
| -rw-r--r-- | drivers/i2c/algos/i2c-algo-pca.c | 6 | ||||
| -rw-r--r-- | drivers/i2c/busses/Kconfig | 6 | ||||
| -rw-r--r-- | drivers/i2c/busses/Makefile | 5 | ||||
| -rw-r--r-- | drivers/i2c/busses/i2c-designware-core.c | 11 | ||||
| -rw-r--r-- | drivers/i2c/busses/i2c-i801.c | 3 | ||||
| -rw-r--r-- | drivers/i2c/busses/i2c-mxs.c | 13 | ||||
| -rw-r--r-- | drivers/i2c/busses/i2c-pnx.c | 53 | ||||
| -rw-r--r-- | drivers/i2c/i2c-core.c | 22 | 
8 files changed, 83 insertions, 36 deletions
diff --git a/drivers/i2c/algos/i2c-algo-pca.c b/drivers/i2c/algos/i2c-algo-pca.c index 73133b1063f..6f5f98d69af 100644 --- a/drivers/i2c/algos/i2c-algo-pca.c +++ b/drivers/i2c/algos/i2c-algo-pca.c @@ -476,17 +476,17 @@ static int pca_init(struct i2c_adapter *adap)  		/* To avoid integer overflow, use clock/100 for calculations */  		clock = pca_clock(pca_data) / 100; -		if (pca_data->i2c_clock > 10000) { +		if (pca_data->i2c_clock > 1000000) {  			mode = I2C_PCA_MODE_TURBO;  			min_tlow = 14;  			min_thi  = 5;  			raise_fall_time = 22; /* Raise 11e-8s, Fall 11e-8s */ -		} else if (pca_data->i2c_clock > 4000) { +		} else if (pca_data->i2c_clock > 400000) {  			mode = I2C_PCA_MODE_FASTP;  			min_tlow = 17;  			min_thi  = 9;  			raise_fall_time = 22; /* Raise 11e-8s, Fall 11e-8s */ -		} else if (pca_data->i2c_clock > 1000) { +		} else if (pca_data->i2c_clock > 100000) {  			mode = I2C_PCA_MODE_FAST;  			min_tlow = 44;  			min_thi  = 20; diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index b4aaa1bd672..970a1612e79 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -104,6 +104,7 @@ config I2C_I801  	    DH89xxCC (PCH)  	    Panther Point (PCH)  	    Lynx Point (PCH) +	    Lynx Point-LP (PCH)  	  This driver can also be built as a module.  If so, the module  	  will be called i2c-i801. @@ -354,9 +355,13 @@ config I2C_DAVINCI  	  devices such as DaVinci NIC.  	  For details please see http://www.ti.com/davinci +config I2C_DESIGNWARE_CORE +	tristate +  config I2C_DESIGNWARE_PLATFORM  	tristate "Synopsys DesignWare Platform"  	depends on HAVE_CLK +	select I2C_DESIGNWARE_CORE  	help  	  If you say yes to this option, support will be included for the  	  Synopsys DesignWare I2C adapter. Only master mode is supported. @@ -367,6 +372,7 @@ config I2C_DESIGNWARE_PLATFORM  config I2C_DESIGNWARE_PCI  	tristate "Synopsys DesignWare PCI"  	depends on PCI +	select I2C_DESIGNWARE_CORE  	help  	  If you say yes to this option, support will be included for the  	  Synopsys DesignWare I2C adapter. Only master mode is supported. diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile index ce3c2be7fb4..37c4182cc98 100644 --- a/drivers/i2c/busses/Makefile +++ b/drivers/i2c/busses/Makefile @@ -33,10 +33,11 @@ obj-$(CONFIG_I2C_AU1550)	+= i2c-au1550.o  obj-$(CONFIG_I2C_BLACKFIN_TWI)	+= i2c-bfin-twi.o  obj-$(CONFIG_I2C_CPM)		+= i2c-cpm.o  obj-$(CONFIG_I2C_DAVINCI)	+= i2c-davinci.o +obj-$(CONFIG_I2C_DESIGNWARE_CORE)	+= i2c-designware-core.o  obj-$(CONFIG_I2C_DESIGNWARE_PLATFORM)	+= i2c-designware-platform.o -i2c-designware-platform-objs := i2c-designware-platdrv.o i2c-designware-core.o +i2c-designware-platform-objs := i2c-designware-platdrv.o  obj-$(CONFIG_I2C_DESIGNWARE_PCI)	+= i2c-designware-pci.o -i2c-designware-pci-objs := i2c-designware-pcidrv.o i2c-designware-core.o +i2c-designware-pci-objs := i2c-designware-pcidrv.o  obj-$(CONFIG_I2C_EG20T)		+= i2c-eg20t.o  obj-$(CONFIG_I2C_GPIO)		+= i2c-gpio.o  obj-$(CONFIG_I2C_HIGHLANDER)	+= i2c-highlander.o diff --git a/drivers/i2c/busses/i2c-designware-core.c b/drivers/i2c/busses/i2c-designware-core.c index 1e48bec80ed..7b8ebbefb58 100644 --- a/drivers/i2c/busses/i2c-designware-core.c +++ b/drivers/i2c/busses/i2c-designware-core.c @@ -25,6 +25,7 @@   * ----------------------------------------------------------------------------   *   */ +#include <linux/export.h>  #include <linux/clk.h>  #include <linux/errno.h>  #include <linux/err.h> @@ -316,6 +317,7 @@ int i2c_dw_init(struct dw_i2c_dev *dev)  	dw_writel(dev, dev->master_cfg , DW_IC_CON);  	return 0;  } +EXPORT_SYMBOL_GPL(i2c_dw_init);  /*   * Waiting for bus not busy @@ -568,12 +570,14 @@ done:  	return ret;  } +EXPORT_SYMBOL_GPL(i2c_dw_xfer);  u32 i2c_dw_func(struct i2c_adapter *adap)  {  	struct dw_i2c_dev *dev = i2c_get_adapdata(adap);  	return dev->functionality;  } +EXPORT_SYMBOL_GPL(i2c_dw_func);  static u32 i2c_dw_read_clear_intrbits(struct dw_i2c_dev *dev)  { @@ -678,17 +682,20 @@ tx_aborted:  	return IRQ_HANDLED;  } +EXPORT_SYMBOL_GPL(i2c_dw_isr);  void i2c_dw_enable(struct dw_i2c_dev *dev)  {         /* Enable the adapter */  	dw_writel(dev, 1, DW_IC_ENABLE);  } +EXPORT_SYMBOL_GPL(i2c_dw_enable);  u32 i2c_dw_is_enabled(struct dw_i2c_dev *dev)  {  	return dw_readl(dev, DW_IC_ENABLE);  } +EXPORT_SYMBOL_GPL(i2c_dw_is_enabled);  void i2c_dw_disable(struct dw_i2c_dev *dev)  { @@ -699,18 +706,22 @@ void i2c_dw_disable(struct dw_i2c_dev *dev)  	dw_writel(dev, 0, DW_IC_INTR_MASK);  	dw_readl(dev, DW_IC_CLR_INTR);  } +EXPORT_SYMBOL_GPL(i2c_dw_disable);  void i2c_dw_clear_int(struct dw_i2c_dev *dev)  {  	dw_readl(dev, DW_IC_CLR_INTR);  } +EXPORT_SYMBOL_GPL(i2c_dw_clear_int);  void i2c_dw_disable_int(struct dw_i2c_dev *dev)  {  	dw_writel(dev, 0, DW_IC_INTR_MASK);  } +EXPORT_SYMBOL_GPL(i2c_dw_disable_int);  u32 i2c_dw_read_comp_param(struct dw_i2c_dev *dev)  {  	return dw_readl(dev, DW_IC_COMP_PARAM_1);  } +EXPORT_SYMBOL_GPL(i2c_dw_read_comp_param); diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index 898dcf9c7ad..33e9b0c09af 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c @@ -52,6 +52,7 @@    DH89xxCC (PCH)        0x2330     32     hard     yes     yes     yes    Panther Point (PCH)   0x1e22     32     hard     yes     yes     yes    Lynx Point (PCH)      0x8c22     32     hard     yes     yes     yes +  Lynx Point-LP (PCH)   0x9c22     32     hard     yes     yes     yes    Features supported by this driver:    Software PEC                     no @@ -155,6 +156,7 @@  #define PCI_DEVICE_ID_INTEL_DH89XXCC_SMBUS	0x2330  #define PCI_DEVICE_ID_INTEL_5_3400_SERIES_SMBUS	0x3b30  #define PCI_DEVICE_ID_INTEL_LYNXPOINT_SMBUS	0x8c22 +#define PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_SMBUS	0x9c22  struct i801_priv {  	struct i2c_adapter adapter; @@ -771,6 +773,7 @@ static DEFINE_PCI_DEVICE_TABLE(i801_ids) = {  	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_DH89XXCC_SMBUS) },  	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PANTHERPOINT_SMBUS) },  	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_LYNXPOINT_SMBUS) }, +	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_SMBUS) },  	{ 0, }  }; diff --git a/drivers/i2c/busses/i2c-mxs.c b/drivers/i2c/busses/i2c-mxs.c index 088c5c1ed17..51f05b8520e 100644 --- a/drivers/i2c/busses/i2c-mxs.c +++ b/drivers/i2c/busses/i2c-mxs.c @@ -365,10 +365,6 @@ static int mxs_i2c_get_ofdata(struct mxs_i2c_dev *i2c)  	struct device_node *node = dev->of_node;  	int ret; -	if (!node) -		return -EINVAL; - -	i2c->speed = &mxs_i2c_95kHz_config;  	ret = of_property_read_u32(node, "clock-frequency", &speed);  	if (ret)  		dev_warn(dev, "No I2C speed selected, using 100kHz\n"); @@ -419,10 +415,13 @@ static int __devinit mxs_i2c_probe(struct platform_device *pdev)  		return err;  	i2c->dev = dev; +	i2c->speed = &mxs_i2c_95kHz_config; -	err = mxs_i2c_get_ofdata(i2c); -	if (err) -		return err; +	if (dev->of_node) { +		err = mxs_i2c_get_ofdata(i2c); +		if (err) +			return err; +	}  	platform_set_drvdata(pdev, i2c); diff --git a/drivers/i2c/busses/i2c-pnx.c b/drivers/i2c/busses/i2c-pnx.c index 5d54416770b..8488bddfe46 100644 --- a/drivers/i2c/busses/i2c-pnx.c +++ b/drivers/i2c/busses/i2c-pnx.c @@ -48,8 +48,9 @@ enum {  	mcntrl_afie = 0x00000002,  	mcntrl_naie = 0x00000004,  	mcntrl_drmie = 0x00000008, -	mcntrl_daie = 0x00000020, -	mcntrl_rffie = 0x00000040, +	mcntrl_drsie = 0x00000010, +	mcntrl_rffie = 0x00000020, +	mcntrl_daie = 0x00000040,  	mcntrl_tffie = 0x00000080,  	mcntrl_reset = 0x00000100,  	mcntrl_cdbmode = 0x00000400, @@ -290,31 +291,37 @@ static int i2c_pnx_master_rcv(struct i2c_pnx_algo_data *alg_data)  	 * or we didn't 'ask' for it yet.  	 */  	if (ioread32(I2C_REG_STS(alg_data)) & mstatus_rfe) { -		dev_dbg(&alg_data->adapter.dev, -			"%s(): Write dummy data to fill Rx-fifo...\n", -			__func__); +		/* 'Asking' is done asynchronously, e.g. dummy TX of several +		 * bytes is done before the first actual RX arrives in FIFO. +		 * Therefore, ordered bytes (via TX) are counted separately. +		 */ +		if (alg_data->mif.order) { +			dev_dbg(&alg_data->adapter.dev, +				"%s(): Write dummy data to fill Rx-fifo...\n", +				__func__); -		if (alg_data->mif.len == 1) { -			/* Last byte, do not acknowledge next rcv. */ -			val |= stop_bit; +			if (alg_data->mif.order == 1) { +				/* Last byte, do not acknowledge next rcv. */ +				val |= stop_bit; + +				/* +				 * Enable interrupt RFDAIE (data in Rx fifo), +				 * and disable DRMIE (need data for Tx) +				 */ +				ctl = ioread32(I2C_REG_CTL(alg_data)); +				ctl |= mcntrl_rffie | mcntrl_daie; +				ctl &= ~mcntrl_drmie; +				iowrite32(ctl, I2C_REG_CTL(alg_data)); +			}  			/* -			 * Enable interrupt RFDAIE (data in Rx fifo), -			 * and disable DRMIE (need data for Tx) +			 * Now we'll 'ask' for data: +			 * For each byte we want to receive, we must +			 * write a (dummy) byte to the Tx-FIFO.  			 */ -			ctl = ioread32(I2C_REG_CTL(alg_data)); -			ctl |= mcntrl_rffie | mcntrl_daie; -			ctl &= ~mcntrl_drmie; -			iowrite32(ctl, I2C_REG_CTL(alg_data)); +			iowrite32(val, I2C_REG_TX(alg_data)); +			alg_data->mif.order--;  		} - -		/* -		 * Now we'll 'ask' for data: -		 * For each byte we want to receive, we must -		 * write a (dummy) byte to the Tx-FIFO. -		 */ -		iowrite32(val, I2C_REG_TX(alg_data)); -  		return 0;  	} @@ -514,6 +521,7 @@ i2c_pnx_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)  		alg_data->mif.buf = pmsg->buf;  		alg_data->mif.len = pmsg->len; +		alg_data->mif.order = pmsg->len;  		alg_data->mif.mode = (pmsg->flags & I2C_M_RD) ?  			I2C_SMBUS_READ : I2C_SMBUS_WRITE;  		alg_data->mif.ret = 0; @@ -566,6 +574,7 @@ i2c_pnx_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)  	/* Cleanup to be sure... */  	alg_data->mif.buf = NULL;  	alg_data->mif.len = 0; +	alg_data->mif.order = 0;  	dev_dbg(&alg_data->adapter.dev, "%s(): exiting, stat = %x\n",  		__func__, ioread32(I2C_REG_STS(alg_data))); diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index 2efa56c5ff2..2091ae8f539 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -637,6 +637,22 @@ static void i2c_adapter_dev_release(struct device *dev)  }  /* + * This function is only needed for mutex_lock_nested, so it is never + * called unless locking correctness checking is enabled. Thus we + * make it inline to avoid a compiler warning. That's what gcc ends up + * doing anyway. + */ +static inline unsigned int i2c_adapter_depth(struct i2c_adapter *adapter) +{ +	unsigned int depth = 0; + +	while ((adapter = i2c_parent_is_i2c_adapter(adapter))) +		depth++; + +	return depth; +} + +/*   * Let users instantiate I2C devices through sysfs. This can be used when   * platform initialization code doesn't contain the proper data for   * whatever reason. Also useful for drivers that do device detection and @@ -726,7 +742,8 @@ i2c_sysfs_delete_device(struct device *dev, struct device_attribute *attr,  	/* Make sure the device was added through sysfs */  	res = -ENOENT; -	mutex_lock(&adap->userspace_clients_lock); +	mutex_lock_nested(&adap->userspace_clients_lock, +			  i2c_adapter_depth(adap));  	list_for_each_entry_safe(client, next, &adap->userspace_clients,  				 detected) {  		if (client->addr == addr) { @@ -1073,7 +1090,8 @@ int i2c_del_adapter(struct i2c_adapter *adap)  		return res;  	/* Remove devices instantiated from sysfs */ -	mutex_lock(&adap->userspace_clients_lock); +	mutex_lock_nested(&adap->userspace_clients_lock, +			  i2c_adapter_depth(adap));  	list_for_each_entry_safe(client, next, &adap->userspace_clients,  				 detected) {  		dev_dbg(&adap->dev, "Removing %s at 0x%x\n", client->name,  |