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-designware-core.c | 11 | ||||
| -rw-r--r-- | drivers/i2c/busses/i2c-i801.c | 3 | ||||
| -rw-r--r-- | drivers/i2c/busses/i2c-iop3xx.c | 121 | ||||
| -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 | 
9 files changed, 145 insertions, 97 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-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-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-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,  | 
