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 | 8 | ||||
| -rw-r--r-- | drivers/i2c/busses/Makefile | 5 | ||||
| -rw-r--r-- | drivers/i2c/busses/i2c-davinci.c | 2 | ||||
| -rw-r--r-- | drivers/i2c/busses/i2c-designware-core.c | 11 | ||||
| -rw-r--r-- | drivers/i2c/busses/i2c-diolan-u2c.c | 1 | ||||
| -rw-r--r-- | drivers/i2c/busses/i2c-i801.c | 3 | ||||
| -rw-r--r-- | drivers/i2c/busses/i2c-imx.c | 2 | ||||
| -rw-r--r-- | drivers/i2c/busses/i2c-iop3xx.c | 121 | ||||
| -rw-r--r-- | drivers/i2c/busses/i2c-mpc.c | 12 | ||||
| -rw-r--r-- | drivers/i2c/busses/i2c-mxs.c | 13 | ||||
| -rw-r--r-- | drivers/i2c/busses/i2c-nomadik.c | 28 | ||||
| -rw-r--r-- | drivers/i2c/busses/i2c-nuc900.c | 2 | ||||
| -rw-r--r-- | drivers/i2c/busses/i2c-omap.c | 5 | ||||
| -rw-r--r-- | drivers/i2c/busses/i2c-pnx.c | 53 | ||||
| -rw-r--r-- | drivers/i2c/busses/i2c-s3c2410.c | 2 | ||||
| -rw-r--r-- | drivers/i2c/busses/i2c-tegra.c | 132 | ||||
| -rw-r--r-- | drivers/i2c/i2c-core.c | 22 | 
18 files changed, 270 insertions, 158 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..42d9fdd63de 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. @@ -545,7 +551,7 @@ config I2C_PMCMSP  config I2C_PNX  	tristate "I2C bus support for Philips PNX and NXP LPC targets" -	depends on ARCH_PNX4008 || ARCH_LPC32XX +	depends on ARCH_LPC32XX  	help  	  This driver supports the Philips IP3204 I2C IP block master and/or  	  slave controller 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-davinci.c b/drivers/i2c/busses/i2c-davinci.c index 79b4bcb3b85..79a2542d8c4 100644 --- a/drivers/i2c/busses/i2c-davinci.c +++ b/drivers/i2c/busses/i2c-davinci.c @@ -40,7 +40,7 @@  #include <linux/gpio.h>  #include <mach/hardware.h> -#include <mach/i2c.h> +#include <linux/platform_data/i2c-davinci.h>  /* ----- global defines ----------------------------------------------- */ 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-diolan-u2c.c b/drivers/i2c/busses/i2c-diolan-u2c.c index aedb94f34bf..dae3ddfe761 100644 --- a/drivers/i2c/busses/i2c-diolan-u2c.c +++ b/drivers/i2c/busses/i2c-diolan-u2c.c @@ -405,6 +405,7 @@ static int diolan_usb_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs,  			}  		}  	} +	ret = num;  abort:  	sret = diolan_i2c_stop(dev);  	if (sret < 0 && ret >= 0) 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-imx.c b/drivers/i2c/busses/i2c-imx.c index 0722f869465..b7907ba7448 100644 --- a/drivers/i2c/busses/i2c-imx.c +++ b/drivers/i2c/busses/i2c-imx.c @@ -54,7 +54,7 @@  #include <linux/pinctrl/consumer.h>  #include <mach/hardware.h> -#include <mach/i2c.h> +#include <linux/platform_data/i2c-imx.h>  /** Defines ********************************************************************  *******************************************************************************/ diff --git a/drivers/i2c/busses/i2c-iop3xx.c b/drivers/i2c/busses/i2c-iop3xx.c index 93f147a96b6..2f99613fd67 100644 --- a/drivers/i2c/busses/i2c-iop3xx.c +++ b/drivers/i2c/busses/i2c-iop3xx.c @@ -4,13 +4,13 @@  /* Copyright (C) 2003 Peter Milne, D-TACQ Solutions Ltd   *                    <Peter dot Milne at D hyphen TACQ dot com>   * - * With acknowledgements to i2c-algo-ibm_ocp.c by  + * With acknowledgements to i2c-algo-ibm_ocp.c by   * Ian DaSilva, MontaVista Software, Inc. idasilva@mvista.com   *   * And i2c-algo-pcf.c, which was created by Simon G. Vogl and Hans Berglund:   *   * Copyright (C) 1995-1997 Simon G. Vogl, 1998-2000 Hans Berglund - *   + *   * And which acknowledged Kyösti Mälkki <kmalkki@cc.hut.fi>,   * Frodo Looijaard <frodol@dds.nl>, Martin Bailey<mbailey@littlefeet-inc.com>   * @@ -39,14 +39,15 @@  #include <linux/platform_device.h>  #include <linux/i2c.h>  #include <linux/io.h> +#include <linux/gpio.h>  #include "i2c-iop3xx.h"  /* global unit counter */  static int i2c_id; -static inline unsigned char  -iic_cook_addr(struct i2c_msg *msg)  +static inline unsigned char +iic_cook_addr(struct i2c_msg *msg)  {  	unsigned char addr; @@ -55,38 +56,38 @@ iic_cook_addr(struct i2c_msg *msg)  	if (msg->flags & I2C_M_RD)  		addr |= 1; -	return addr;    +	return addr;  } -static void  +static void  iop3xx_i2c_reset(struct i2c_algo_iop3xx_data *iop3xx_adap)  {  	/* Follows devman 9.3 */  	__raw_writel(IOP3XX_ICR_UNIT_RESET, iop3xx_adap->ioaddr + CR_OFFSET);  	__raw_writel(IOP3XX_ISR_CLEARBITS, iop3xx_adap->ioaddr + SR_OFFSET);  	__raw_writel(0, iop3xx_adap->ioaddr + CR_OFFSET); -}  +} -static void  +static void  iop3xx_i2c_enable(struct i2c_algo_iop3xx_data *iop3xx_adap)  {  	u32 cr = IOP3XX_ICR_GCD | IOP3XX_ICR_SCLEN | IOP3XX_ICR_UE; -	/*  +	/*  	 * Every time unit enable is asserted, GPOD needs to be cleared  	 * on IOP3XX to avoid data corruption on the bus.  	 */  #if defined(CONFIG_ARCH_IOP32X) || defined(CONFIG_ARCH_IOP33X)  	if (iop3xx_adap->id == 0) { -		gpio_line_set(IOP3XX_GPIO_LINE(7), GPIO_LOW); -		gpio_line_set(IOP3XX_GPIO_LINE(6), GPIO_LOW); +		gpio_set_value(7, 0); +		gpio_set_value(6, 0);  	} else { -		gpio_line_set(IOP3XX_GPIO_LINE(5), GPIO_LOW); -		gpio_line_set(IOP3XX_GPIO_LINE(4), GPIO_LOW); +		gpio_set_value(5, 0); +		gpio_set_value(4, 0);  	}  #endif  	/* NB SR bits not same position as CR IE bits :-( */ -	iop3xx_adap->SR_enabled =  +	iop3xx_adap->SR_enabled =  		IOP3XX_ISR_ALD | IOP3XX_ISR_BERRD |  		IOP3XX_ISR_RXFULL | IOP3XX_ISR_TXEMPTY; @@ -96,23 +97,23 @@ iop3xx_i2c_enable(struct i2c_algo_iop3xx_data *iop3xx_adap)  	__raw_writel(cr, iop3xx_adap->ioaddr + CR_OFFSET);  } -static void  +static void  iop3xx_i2c_transaction_cleanup(struct i2c_algo_iop3xx_data *iop3xx_adap)  {  	unsigned long cr = __raw_readl(iop3xx_adap->ioaddr + CR_OFFSET); -	 -	cr &= ~(IOP3XX_ICR_MSTART | IOP3XX_ICR_TBYTE |  + +	cr &= ~(IOP3XX_ICR_MSTART | IOP3XX_ICR_TBYTE |  		IOP3XX_ICR_MSTOP | IOP3XX_ICR_SCLEN);  	__raw_writel(cr, iop3xx_adap->ioaddr + CR_OFFSET);  } -/*  - * NB: the handler has to clear the source of the interrupt!  +/* + * NB: the handler has to clear the source of the interrupt!   * Then it passes the SR flags of interest to BH via adap data   */ -static irqreturn_t  -iop3xx_i2c_irq_handler(int this_irq, void *dev_id)  +static irqreturn_t +iop3xx_i2c_irq_handler(int this_irq, void *dev_id)  {  	struct i2c_algo_iop3xx_data *iop3xx_adap = dev_id;  	u32 sr = __raw_readl(iop3xx_adap->ioaddr + SR_OFFSET); @@ -126,7 +127,7 @@ iop3xx_i2c_irq_handler(int this_irq, void *dev_id)  }  /* check all error conditions, clear them , report most important */ -static int  +static int  iop3xx_i2c_error(u32 sr)  {  	int rc = 0; @@ -135,12 +136,12 @@ iop3xx_i2c_error(u32 sr)  		if ( !rc ) rc = -I2C_ERR_BERR;  	}  	if ((sr & IOP3XX_ISR_ALD)) { -		if ( !rc ) rc = -I2C_ERR_ALD;		 +		if ( !rc ) rc = -I2C_ERR_ALD;  	} -	return rc;	 +	return rc;  } -static inline u32  +static inline u32  iop3xx_i2c_get_srstat(struct i2c_algo_iop3xx_data *iop3xx_adap)  {  	unsigned long flags; @@ -161,8 +162,8 @@ iop3xx_i2c_get_srstat(struct i2c_algo_iop3xx_data *iop3xx_adap)  typedef int (* compare_func)(unsigned test, unsigned mask);  /* returns 1 on correct comparison */ -static int  -iop3xx_i2c_wait_event(struct i2c_algo_iop3xx_data *iop3xx_adap,  +static int +iop3xx_i2c_wait_event(struct i2c_algo_iop3xx_data *iop3xx_adap,  			  unsigned flags, unsigned* status,  			  compare_func compare)  { @@ -192,47 +193,47 @@ iop3xx_i2c_wait_event(struct i2c_algo_iop3xx_data *iop3xx_adap,  }  /* - * Concrete compare_funcs  + * Concrete compare_funcs   */ -static int  +static int  all_bits_clear(unsigned test, unsigned mask)  {  	return (test & mask) == 0;  } -static int  +static int  any_bits_set(unsigned test, unsigned mask)  {  	return (test & mask) != 0;  } -static int  +static int  iop3xx_i2c_wait_tx_done(struct i2c_algo_iop3xx_data *iop3xx_adap, int *status)  { -	return iop3xx_i2c_wait_event(  -		iop3xx_adap,  +	return iop3xx_i2c_wait_event( +		iop3xx_adap,  	        IOP3XX_ISR_TXEMPTY | IOP3XX_ISR_ALD | IOP3XX_ISR_BERRD,  		status, any_bits_set);  } -static int  +static int  iop3xx_i2c_wait_rx_done(struct i2c_algo_iop3xx_data *iop3xx_adap, int *status)  { -	return iop3xx_i2c_wait_event(  -		iop3xx_adap,  +	return iop3xx_i2c_wait_event( +		iop3xx_adap,  		IOP3XX_ISR_RXFULL | IOP3XX_ISR_ALD | IOP3XX_ISR_BERRD,  		status,	any_bits_set);  } -static int  +static int  iop3xx_i2c_wait_idle(struct i2c_algo_iop3xx_data *iop3xx_adap, int *status)  { -	return iop3xx_i2c_wait_event(  +	return iop3xx_i2c_wait_event(  		iop3xx_adap, IOP3XX_ISR_UNITBUSY, status, all_bits_clear);  } -static int  -iop3xx_i2c_send_target_addr(struct i2c_algo_iop3xx_data *iop3xx_adap,  +static int +iop3xx_i2c_send_target_addr(struct i2c_algo_iop3xx_data *iop3xx_adap,  				struct i2c_msg* msg)  {  	unsigned long cr = __raw_readl(iop3xx_adap->ioaddr + CR_OFFSET); @@ -247,7 +248,7 @@ iop3xx_i2c_send_target_addr(struct i2c_algo_iop3xx_data *iop3xx_adap,  	}  	__raw_writel(iic_cook_addr(msg), iop3xx_adap->ioaddr + DBR_OFFSET); -	 +  	cr &= ~(IOP3XX_ICR_MSTOP | IOP3XX_ICR_NACK);  	cr |= IOP3XX_ICR_MSTART | IOP3XX_ICR_TBYTE; @@ -257,8 +258,8 @@ iop3xx_i2c_send_target_addr(struct i2c_algo_iop3xx_data *iop3xx_adap,  	return rc;  } -static int  -iop3xx_i2c_write_byte(struct i2c_algo_iop3xx_data *iop3xx_adap, char byte,  +static int +iop3xx_i2c_write_byte(struct i2c_algo_iop3xx_data *iop3xx_adap, char byte,  				int stop)  {  	unsigned long cr = __raw_readl(iop3xx_adap->ioaddr + CR_OFFSET); @@ -277,10 +278,10 @@ iop3xx_i2c_write_byte(struct i2c_algo_iop3xx_data *iop3xx_adap, char byte,  	rc = iop3xx_i2c_wait_tx_done(iop3xx_adap, &status);  	return rc; -}  +} -static int  -iop3xx_i2c_read_byte(struct i2c_algo_iop3xx_data *iop3xx_adap, char* byte,  +static int +iop3xx_i2c_read_byte(struct i2c_algo_iop3xx_data *iop3xx_adap, char* byte,  				int stop)  {  	unsigned long cr = __raw_readl(iop3xx_adap->ioaddr + CR_OFFSET); @@ -304,19 +305,19 @@ iop3xx_i2c_read_byte(struct i2c_algo_iop3xx_data *iop3xx_adap, char* byte,  	return rc;  } -static int  +static int  iop3xx_i2c_writebytes(struct i2c_adapter *i2c_adap, const char *buf, int count)  {  	struct i2c_algo_iop3xx_data *iop3xx_adap = i2c_adap->algo_data;  	int ii;  	int rc = 0; -	for (ii = 0; rc == 0 && ii != count; ++ii)  +	for (ii = 0; rc == 0 && ii != count; ++ii)  		rc = iop3xx_i2c_write_byte(iop3xx_adap, buf[ii], ii==count-1);  	return rc;  } -static int  +static int  iop3xx_i2c_readbytes(struct i2c_adapter *i2c_adap, char *buf, int count)  {  	struct i2c_algo_iop3xx_data *iop3xx_adap = i2c_adap->algo_data; @@ -325,7 +326,7 @@ iop3xx_i2c_readbytes(struct i2c_adapter *i2c_adap, char *buf, int count)  	for (ii = 0; rc == 0 && ii != count; ++ii)  		rc = iop3xx_i2c_read_byte(iop3xx_adap, &buf[ii], ii==count-1); -	 +  	return rc;  } @@ -336,8 +337,8 @@ iop3xx_i2c_readbytes(struct i2c_adapter *i2c_adap, char *buf, int count)   * Each transfer (i.e. a read or a write) is separated by a repeated start   * condition.   */ -static int  -iop3xx_i2c_handle_msg(struct i2c_adapter *i2c_adap, struct i2c_msg* pmsg)  +static int +iop3xx_i2c_handle_msg(struct i2c_adapter *i2c_adap, struct i2c_msg* pmsg)  {  	struct i2c_algo_iop3xx_data *iop3xx_adap = i2c_adap->algo_data;  	int rc; @@ -357,8 +358,8 @@ iop3xx_i2c_handle_msg(struct i2c_adapter *i2c_adap, struct i2c_msg* pmsg)  /*   * master_xfer() - main read/write entry   */ -static int  -iop3xx_i2c_master_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs,  +static int +iop3xx_i2c_master_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs,  				int num)  {  	struct i2c_algo_iop3xx_data *iop3xx_adap = i2c_adap->algo_data; @@ -375,14 +376,14 @@ iop3xx_i2c_master_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs,  	}  	iop3xx_i2c_transaction_cleanup(iop3xx_adap); -	 +  	if(ret)  		return ret; -	return im;    +	return im;  } -static u32  +static u32  iop3xx_i2c_func(struct i2c_adapter *adap)  {  	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; @@ -393,11 +394,11 @@ static const struct i2c_algorithm iop3xx_i2c_algo = {  	.functionality	= iop3xx_i2c_func,  }; -static int  +static int  iop3xx_i2c_remove(struct platform_device *pdev)  {  	struct i2c_adapter *padapter = platform_get_drvdata(pdev); -	struct i2c_algo_iop3xx_data *adapter_data =  +	struct i2c_algo_iop3xx_data *adapter_data =  		(struct i2c_algo_iop3xx_data *)padapter->algo_data;  	struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);  	unsigned long cr = __raw_readl(adapter_data->ioaddr + CR_OFFSET); @@ -419,7 +420,7 @@ iop3xx_i2c_remove(struct platform_device *pdev)  	return 0;  } -static int  +static int  iop3xx_i2c_probe(struct platform_device *pdev)  {  	struct resource *res; diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c index b76731edbf1..57f7703ce2e 100644 --- a/drivers/i2c/busses/i2c-mpc.c +++ b/drivers/i2c/busses/i2c-mpc.c @@ -647,7 +647,7 @@ static int __devinit fsl_i2c_probe(struct platform_device *op)  	}  	if (match->data) { -		struct mpc_i2c_data *data = match->data; +		const struct mpc_i2c_data *data = match->data;  		data->setup(op->dev.of_node, i2c, clock, data->prescaler);  	} else {  		/* Backwards compatibility */ @@ -730,24 +730,24 @@ static int mpc_i2c_resume(struct device *dev)  SIMPLE_DEV_PM_OPS(mpc_i2c_pm_ops, mpc_i2c_suspend, mpc_i2c_resume);  #endif -static struct mpc_i2c_data mpc_i2c_data_512x __devinitdata = { +static const struct mpc_i2c_data mpc_i2c_data_512x __devinitdata = {  	.setup = mpc_i2c_setup_512x,  }; -static struct mpc_i2c_data mpc_i2c_data_52xx __devinitdata = { +static const struct mpc_i2c_data mpc_i2c_data_52xx __devinitdata = {  	.setup = mpc_i2c_setup_52xx,  }; -static struct mpc_i2c_data mpc_i2c_data_8313 __devinitdata = { +static const struct mpc_i2c_data mpc_i2c_data_8313 __devinitdata = {  	.setup = mpc_i2c_setup_8xxx,  }; -static struct mpc_i2c_data mpc_i2c_data_8543 __devinitdata = { +static const struct mpc_i2c_data mpc_i2c_data_8543 __devinitdata = {  	.setup = mpc_i2c_setup_8xxx,  	.prescaler = 2,  }; -static struct mpc_i2c_data mpc_i2c_data_8544 __devinitdata = { +static const struct mpc_i2c_data mpc_i2c_data_8544 __devinitdata = {  	.setup = mpc_i2c_setup_8xxx,  	.prescaler = 3,  }; 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-nomadik.c b/drivers/i2c/busses/i2c-nomadik.c index 5e6f1eed4f8..61b00edacb0 100644 --- a/drivers/i2c/busses/i2c-nomadik.c +++ b/drivers/i2c/busses/i2c-nomadik.c @@ -350,10 +350,6 @@ static void setup_i2c_controller(struct nmk_i2c_dev *dev)  	i2c_clk = clk_get_rate(dev->clk); -	/* fallback to std. mode if machine has not provided it */ -	if (dev->cfg.clk_freq == 0) -		dev->cfg.clk_freq = 100000; -  	/*  	 * The spec says, in case of std. mode the divider is  	 * 2 whereas it is 3 for fast and fastplus mode of @@ -911,20 +907,32 @@ static const struct i2c_algorithm nmk_i2c_algo = {  	.functionality	= nmk_i2c_functionality  }; +static struct nmk_i2c_controller u8500_i2c = { +	/* +	 * Slave data setup time; 250ns, 100ns, and 10ns, which +	 * is 14, 6 and 2 respectively for a 48Mhz i2c clock. +	 */ +	.slsu           = 0xe, +	.tft            = 1,      /* Tx FIFO threshold */ +	.rft            = 8,      /* Rx FIFO threshold */ +	.clk_freq       = 400000, /* fast mode operation */ +	.timeout        = 200,    /* Slave response timeout(ms) */ +	.sm             = I2C_FREQ_MODE_FAST, +}; +  static atomic_t adapter_id = ATOMIC_INIT(0);  static int nmk_i2c_probe(struct amba_device *adev, const struct amba_id *id)  {  	int ret = 0; -	struct nmk_i2c_controller *pdata = -			adev->dev.platform_data; +	struct nmk_i2c_controller *pdata = adev->dev.platform_data;  	struct nmk_i2c_dev	*dev;  	struct i2c_adapter *adap; -	if (!pdata) { -		dev_warn(&adev->dev, "no platform data\n"); -		return -ENODEV; -	} +	if (!pdata) +		/* No i2c configuration found, using the default. */ +		pdata = &u8500_i2c; +  	dev = kzalloc(sizeof(struct nmk_i2c_dev), GFP_KERNEL);  	if (!dev) {  		dev_err(&adev->dev, "cannot allocate memory\n"); diff --git a/drivers/i2c/busses/i2c-nuc900.c b/drivers/i2c/busses/i2c-nuc900.c index a26dfb8cd58..f41502ef3f5 100644 --- a/drivers/i2c/busses/i2c-nuc900.c +++ b/drivers/i2c/busses/i2c-nuc900.c @@ -29,7 +29,7 @@  #include <linux/io.h>  #include <mach/mfp.h> -#include <mach/i2c.h> +#include <linux/platform_data/i2c-nuc900.h>  /* nuc900 i2c registers offset */ diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index 6849635b268..a0e49f6aaf9 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c @@ -584,7 +584,7 @@ omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)  	r = pm_runtime_get_sync(dev->dev);  	if (IS_ERR_VALUE(r)) -		return r; +		goto out;  	r = omap_i2c_wait_for_bb(dev);  	if (r < 0) @@ -944,7 +944,8 @@ omap_i2c_probe(struct platform_device *pdev)  	struct omap_i2c_dev	*dev;  	struct i2c_adapter	*adap;  	struct resource		*mem, *irq, *ioarea; -	struct omap_i2c_bus_platform_data *pdata = pdev->dev.platform_data; +	const struct omap_i2c_bus_platform_data *pdata = +		pdev->dev.platform_data;  	struct device_node	*node = pdev->dev.of_node;  	const struct of_device_id *match;  	irq_handler_t isr; 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/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c index 5ae3b0236bd..4d07dea9bca 100644 --- a/drivers/i2c/busses/i2c-s3c2410.c +++ b/drivers/i2c/busses/i2c-s3c2410.c @@ -42,7 +42,7 @@  #include <asm/irq.h>  #include <plat/regs-iic.h> -#include <plat/iic.h> +#include <linux/platform_data/i2c-s3c2410.h>  /* Treat S3C2410 as baseline hardware, anything else is supported via quirks */  #define QUIRK_S3C2440		(1 << 0) diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c index 66eb53fac20..f981ac4e678 100644 --- a/drivers/i2c/busses/i2c-tegra.c +++ b/drivers/i2c/busses/i2c-tegra.c @@ -27,6 +27,7 @@  #include <linux/slab.h>  #include <linux/i2c-tegra.h>  #include <linux/of_i2c.h> +#include <linux/of_device.h>  #include <linux/module.h>  #include <asm/unaligned.h> @@ -114,11 +115,21 @@ enum msg_end_type {  };  /** + * struct tegra_i2c_hw_feature : Different HW support on Tegra + * @has_continue_xfer_support: Continue transfer supports. + */ + +struct tegra_i2c_hw_feature { +	bool has_continue_xfer_support; +}; + +/**   * struct tegra_i2c_dev	- per device i2c context   * @dev: device reference for power management + * @hw: Tegra i2c hw feature.   * @adapter: core i2c layer adapter information - * @clk: clock reference for i2c controller - * @i2c_clk: clock reference for i2c bus + * @div_clk: clock reference for div clock of i2c controller. + * @fast_clk: clock reference for fast clock of i2c controller.   * @base: ioremapped registers cookie   * @cont_id: i2c controller id, used for for packet header   * @irq: irq number of transfer complete interrupt @@ -133,9 +144,10 @@ enum msg_end_type {   */  struct tegra_i2c_dev {  	struct device *dev; +	const struct tegra_i2c_hw_feature *hw;  	struct i2c_adapter adapter; -	struct clk *clk; -	struct clk *i2c_clk; +	struct clk *div_clk; +	struct clk *fast_clk;  	void __iomem *base;  	int cont_id;  	int irq; @@ -351,16 +363,40 @@ static void tegra_dvc_init(struct tegra_i2c_dev *i2c_dev)  	dvc_writel(i2c_dev, val, DVC_CTRL_REG1);  } +static inline int tegra_i2c_clock_enable(struct tegra_i2c_dev *i2c_dev) +{ +	int ret; +	ret = clk_prepare_enable(i2c_dev->fast_clk); +	if (ret < 0) { +		dev_err(i2c_dev->dev, +			"Enabling fast clk failed, err %d\n", ret); +		return ret; +	} +	ret = clk_prepare_enable(i2c_dev->div_clk); +	if (ret < 0) { +		dev_err(i2c_dev->dev, +			"Enabling div clk failed, err %d\n", ret); +		clk_disable_unprepare(i2c_dev->fast_clk); +	} +	return ret; +} + +static inline void tegra_i2c_clock_disable(struct tegra_i2c_dev *i2c_dev) +{ +	clk_disable_unprepare(i2c_dev->div_clk); +	clk_disable_unprepare(i2c_dev->fast_clk); +} +  static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev)  {  	u32 val;  	int err = 0; -	clk_prepare_enable(i2c_dev->clk); +	tegra_i2c_clock_enable(i2c_dev); -	tegra_periph_reset_assert(i2c_dev->clk); +	tegra_periph_reset_assert(i2c_dev->div_clk);  	udelay(2); -	tegra_periph_reset_deassert(i2c_dev->clk); +	tegra_periph_reset_deassert(i2c_dev->div_clk);  	if (i2c_dev->is_dvc)  		tegra_dvc_init(i2c_dev); @@ -369,7 +405,7 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev)  		(0x2 << I2C_CNFG_DEBOUNCE_CNT_SHIFT);  	i2c_writel(i2c_dev, val, I2C_CNFG);  	i2c_writel(i2c_dev, 0, I2C_INT_MASK); -	clk_set_rate(i2c_dev->clk, i2c_dev->bus_clk_rate * 8); +	clk_set_rate(i2c_dev->div_clk, i2c_dev->bus_clk_rate * 8);  	if (!i2c_dev->is_dvc) {  		u32 sl_cfg = i2c_readl(i2c_dev, I2C_SL_CNFG); @@ -387,7 +423,7 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev)  	if (tegra_i2c_flush_fifos(i2c_dev))  		err = -ETIMEDOUT; -	clk_disable_unprepare(i2c_dev->clk); +	tegra_i2c_clock_disable(i2c_dev);  	if (i2c_dev->irq_disabled) {  		i2c_dev->irq_disabled = 0; @@ -563,7 +599,7 @@ static int tegra_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[],  	if (i2c_dev->is_suspended)  		return -EBUSY; -	clk_prepare_enable(i2c_dev->clk); +	tegra_i2c_clock_enable(i2c_dev);  	for (i = 0; i < num; i++) {  		enum msg_end_type end_type = MSG_END_STOP;  		if (i < (num - 1)) { @@ -576,14 +612,19 @@ static int tegra_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[],  		if (ret)  			break;  	} -	clk_disable_unprepare(i2c_dev->clk); +	tegra_i2c_clock_disable(i2c_dev);  	return ret ?: i;  }  static u32 tegra_i2c_func(struct i2c_adapter *adap)  { -	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR | -		I2C_FUNC_PROTOCOL_MANGLING | I2C_FUNC_NOSTART; +	struct tegra_i2c_dev *i2c_dev = i2c_get_adapdata(adap); +	u32 ret = I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR | +				I2C_FUNC_PROTOCOL_MANGLING; + +	if (i2c_dev->hw->has_continue_xfer_support) +		ret |= I2C_FUNC_NOSTART; +	return ret;  }  static const struct i2c_algorithm tegra_i2c_algo = { @@ -591,13 +632,32 @@ static const struct i2c_algorithm tegra_i2c_algo = {  	.functionality	= tegra_i2c_func,  }; +static const struct tegra_i2c_hw_feature tegra20_i2c_hw = { +	.has_continue_xfer_support = false, +}; + +static const struct tegra_i2c_hw_feature tegra30_i2c_hw = { +	.has_continue_xfer_support = true, +}; + +#if defined(CONFIG_OF) +/* Match table for of_platform binding */ +static const struct of_device_id tegra_i2c_of_match[] __devinitconst = { +	{ .compatible = "nvidia,tegra30-i2c", .data = &tegra30_i2c_hw, }, +	{ .compatible = "nvidia,tegra20-i2c", .data = &tegra20_i2c_hw, }, +	{ .compatible = "nvidia,tegra20-i2c-dvc", .data = &tegra20_i2c_hw, }, +	{}, +}; +MODULE_DEVICE_TABLE(of, tegra_i2c_of_match); +#endif +  static int __devinit tegra_i2c_probe(struct platform_device *pdev)  {  	struct tegra_i2c_dev *i2c_dev;  	struct tegra_i2c_platform_data *pdata = pdev->dev.platform_data;  	struct resource *res; -	struct clk *clk; -	struct clk *i2c_clk; +	struct clk *div_clk; +	struct clk *fast_clk;  	const unsigned int *prop;  	void __iomem *base;  	int irq; @@ -622,16 +682,16 @@ static int __devinit tegra_i2c_probe(struct platform_device *pdev)  	}  	irq = res->start; -	clk = devm_clk_get(&pdev->dev, NULL); -	if (IS_ERR(clk)) { +	div_clk = devm_clk_get(&pdev->dev, "div-clk"); +	if (IS_ERR(div_clk)) {  		dev_err(&pdev->dev, "missing controller clock"); -		return PTR_ERR(clk); +		return PTR_ERR(div_clk);  	} -	i2c_clk = devm_clk_get(&pdev->dev, "i2c"); -	if (IS_ERR(i2c_clk)) { +	fast_clk = devm_clk_get(&pdev->dev, "fast-clk"); +	if (IS_ERR(fast_clk)) {  		dev_err(&pdev->dev, "missing bus clock"); -		return PTR_ERR(i2c_clk); +		return PTR_ERR(fast_clk);  	}  	i2c_dev = devm_kzalloc(&pdev->dev, sizeof(*i2c_dev), GFP_KERNEL); @@ -641,8 +701,8 @@ static int __devinit tegra_i2c_probe(struct platform_device *pdev)  	}  	i2c_dev->base = base; -	i2c_dev->clk = clk; -	i2c_dev->i2c_clk = i2c_clk; +	i2c_dev->div_clk = div_clk; +	i2c_dev->fast_clk = fast_clk;  	i2c_dev->adapter.algo = &tegra_i2c_algo;  	i2c_dev->irq = irq;  	i2c_dev->cont_id = pdev->id; @@ -659,11 +719,18 @@ static int __devinit tegra_i2c_probe(struct platform_device *pdev)  			i2c_dev->bus_clk_rate = be32_to_cpup(prop);  	} -	if (pdev->dev.of_node) +	i2c_dev->hw = &tegra20_i2c_hw; + +	if (pdev->dev.of_node) { +		const struct of_device_id *match; +		match = of_match_device(of_match_ptr(tegra_i2c_of_match), +						&pdev->dev); +		i2c_dev->hw = match->data;  		i2c_dev->is_dvc = of_device_is_compatible(pdev->dev.of_node,  						"nvidia,tegra20-i2c-dvc"); -	else if (pdev->id == 3) +	} else if (pdev->id == 3) {  		i2c_dev->is_dvc = 1; +	}  	init_completion(&i2c_dev->msg_complete);  	platform_set_drvdata(pdev, i2c_dev); @@ -681,8 +748,6 @@ static int __devinit tegra_i2c_probe(struct platform_device *pdev)  		return ret;  	} -	clk_prepare_enable(i2c_dev->i2c_clk); -  	i2c_set_adapdata(&i2c_dev->adapter, i2c_dev);  	i2c_dev->adapter.owner = THIS_MODULE;  	i2c_dev->adapter.class = I2C_CLASS_HWMON; @@ -696,7 +761,6 @@ static int __devinit tegra_i2c_probe(struct platform_device *pdev)  	ret = i2c_add_numbered_adapter(&i2c_dev->adapter);  	if (ret) {  		dev_err(&pdev->dev, "Failed to add I2C adapter\n"); -		clk_disable_unprepare(i2c_dev->i2c_clk);  		return ret;  	} @@ -712,7 +776,7 @@ static int __devexit tegra_i2c_remove(struct platform_device *pdev)  	return 0;  } -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP  static int tegra_i2c_suspend(struct device *dev)  {  	struct tegra_i2c_dev *i2c_dev = dev_get_drvdata(dev); @@ -751,16 +815,6 @@ static SIMPLE_DEV_PM_OPS(tegra_i2c_pm, tegra_i2c_suspend, tegra_i2c_resume);  #define TEGRA_I2C_PM	NULL  #endif -#if defined(CONFIG_OF) -/* Match table for of_platform binding */ -static const struct of_device_id tegra_i2c_of_match[] __devinitconst = { -	{ .compatible = "nvidia,tegra20-i2c", }, -	{ .compatible = "nvidia,tegra20-i2c-dvc", }, -	{}, -}; -MODULE_DEVICE_TABLE(of, tegra_i2c_of_match); -#endif -  static struct platform_driver tegra_i2c_driver = {  	.probe   = tegra_i2c_probe,  	.remove  = __devexit_p(tegra_i2c_remove), 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,  |