diff options
Diffstat (limited to 'drivers/i2c')
32 files changed, 2449 insertions, 354 deletions
| diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig index d06083fdffb..b923074b2cb 100644 --- a/drivers/i2c/Kconfig +++ b/drivers/i2c/Kconfig @@ -47,6 +47,19 @@ config I2C_CHARDEV  	  This support is also available as a module.  If so, the module   	  will be called i2c-dev. +config I2C_MUX +	tristate "I2C bus multiplexing support" +	depends on EXPERIMENTAL +	help +	  Say Y here if you want the I2C core to support the ability to +	  handle multiplexed I2C bus topologies, by presenting each +	  multiplexed segment as a I2C adapter. + +	  This support is also available as a module.  If so, the module +	  will be called i2c-mux. + +source drivers/i2c/muxes/Kconfig +  config I2C_HELPER_AUTO  	bool "Autoselect pertinent helper modules"  	default y @@ -62,7 +75,8 @@ config I2C_HELPER_AUTO  	  In doubt, say Y.  config I2C_SMBUS -	tristate "SMBus-specific protocols" if !I2C_HELPER_AUTO +	tristate +	prompt "SMBus-specific protocols" if !I2C_HELPER_AUTO  	help  	  Say Y here if you want support for SMBus extensions to the I2C  	  specification. At the moment, the only supported extension is diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile index a7d9b4be9bb..23ac61e2db3 100644 --- a/drivers/i2c/Makefile +++ b/drivers/i2c/Makefile @@ -6,8 +6,7 @@ obj-$(CONFIG_I2C_BOARDINFO)	+= i2c-boardinfo.o  obj-$(CONFIG_I2C)		+= i2c-core.o  obj-$(CONFIG_I2C_SMBUS)		+= i2c-smbus.o  obj-$(CONFIG_I2C_CHARDEV)	+= i2c-dev.o -obj-y				+= algos/ busses/ +obj-$(CONFIG_I2C_MUX)		+= i2c-mux.o +obj-y				+= algos/ busses/ muxes/ -ifeq ($(CONFIG_I2C_DEBUG_CORE),y) -EXTRA_CFLAGS += -DDEBUG -endif +ccflags-$(CONFIG_I2C_DEBUG_CORE) := -DDEBUG diff --git a/drivers/i2c/algos/Kconfig b/drivers/i2c/algos/Kconfig index 7b2ce4a0852..3998dd620a0 100644 --- a/drivers/i2c/algos/Kconfig +++ b/drivers/i2c/algos/Kconfig @@ -15,3 +15,15 @@ config I2C_ALGOPCA  	tristate "I2C PCA 9564 interfaces"  endmenu + +# In automatic configuration mode, we still have to define the +# symbols to avoid unmet dependencies. + +if I2C_HELPER_AUTO +config I2C_ALGOBIT +	tristate +config I2C_ALGOPCF +	tristate +config I2C_ALGOPCA +	tristate +endif diff --git a/drivers/i2c/algos/Makefile b/drivers/i2c/algos/Makefile index 18b3e962ec0..215303f60d6 100644 --- a/drivers/i2c/algos/Makefile +++ b/drivers/i2c/algos/Makefile @@ -6,6 +6,4 @@ obj-$(CONFIG_I2C_ALGOBIT)	+= i2c-algo-bit.o  obj-$(CONFIG_I2C_ALGOPCF)	+= i2c-algo-pcf.o  obj-$(CONFIG_I2C_ALGOPCA)	+= i2c-algo-pca.o -ifeq ($(CONFIG_I2C_DEBUG_ALGO),y) -EXTRA_CFLAGS += -DDEBUG -endif +ccflags-$(CONFIG_I2C_DEBUG_ALGO) := -DDEBUG diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index bceafbfa726..fd455a2fdd1 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -95,9 +95,9 @@ config I2C_I801  	    ESB2  	    ICH8  	    ICH9 -	    Tolapai +	    EP80579 (Tolapai)  	    ICH10 -	    3400/5 Series (PCH) +	    5/3400 Series (PCH)  	    Cougar Point (PCH)  	  This driver can also be built as a module.  If so, the module @@ -448,6 +448,13 @@ config I2C_NOMADIK  	  If you say yes to this option, support will be included for the  	  I2C interface from ST-Ericsson's Nomadik and Ux500 architectures. +config I2C_NUC900 +	tristate "NUC900 I2C Driver" +	depends on ARCH_W90X900 +	help +	  Say Y here to include support for I2C controller in the +	  Winbond/Nuvoton NUC900 based System-on-Chip devices. +  config I2C_OCORES  	tristate "OpenCores I2C Controller"  	depends on EXPERIMENTAL @@ -496,8 +503,8 @@ config I2C_PMCMSP  	  will be called i2c-pmcmsp.  config I2C_PNX -	tristate "I2C bus support for Philips PNX targets" -	depends on ARCH_PNX4008 +	tristate "I2C bus support for Philips PNX and NXP LPC targets" +	depends on ARCH_PNX4008 || ARCH_LPC32XX  	help  	  This driver supports the Philips IP3204 I2C IP block master and/or  	  slave controller @@ -521,12 +528,19 @@ config I2C_PXA_SLAVE  	  is necessary for systems where the PXA may be a target on the  	  I2C bus. +config HAVE_S3C2410_I2C +	bool +	help +	  This will include I2C support for Samsung SoCs. If you want to +	  include I2C support for any machine, kindly select this in the +	  respective Kconfig file. +  config I2C_S3C2410  	tristate "S3C2410 I2C Driver" -	depends on ARCH_S3C2410 || ARCH_S3C64XX +	depends on HAVE_S3C2410_I2C  	help  	  Say Y here to include support for I2C controller in the -	  Samsung S3C2410 based System-on-Chip devices. +	  Samsung SoCs.  config I2C_S6000  	tristate "S6000 I2C support" @@ -549,7 +563,7 @@ config I2C_SH7760  config I2C_SH_MOBILE  	tristate "SuperH Mobile I2C Controller" -	depends on SUPERH +	depends on SUPERH || ARCH_SHMOBILE  	help  	  If you say yes to this option, support will be included for the  	  built-in I2C interface on the Renesas SH-Mobile processor. diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile index 936880bd1dc..033ad413f32 100644 --- a/drivers/i2c/busses/Makefile +++ b/drivers/i2c/busses/Makefile @@ -43,6 +43,7 @@ obj-$(CONFIG_I2C_IXP2000)	+= i2c-ixp2000.o  obj-$(CONFIG_I2C_MPC)		+= i2c-mpc.o  obj-$(CONFIG_I2C_MV64XXX)	+= i2c-mv64xxx.o  obj-$(CONFIG_I2C_NOMADIK)	+= i2c-nomadik.o +obj-$(CONFIG_I2C_NUC900)	+= i2c-nuc900.o  obj-$(CONFIG_I2C_OCORES)	+= i2c-ocores.o  obj-$(CONFIG_I2C_OMAP)		+= i2c-omap.o  obj-$(CONFIG_I2C_PASEMI)	+= i2c-pasemi.o @@ -75,6 +76,4 @@ obj-$(CONFIG_I2C_STUB)		+= i2c-stub.o  obj-$(CONFIG_SCx200_ACB)	+= scx200_acb.o  obj-$(CONFIG_SCx200_I2C)	+= scx200_i2c.o -ifeq ($(CONFIG_I2C_DEBUG_BUS),y) -EXTRA_CFLAGS += -DDEBUG -endif +ccflags-$(CONFIG_I2C_DEBUG_BUS) := -DDEBUG diff --git a/drivers/i2c/busses/i2c-amd8111.c b/drivers/i2c/busses/i2c-amd8111.c index af1e5e254b7..6b6a6b1d702 100644 --- a/drivers/i2c/busses/i2c-amd8111.c +++ b/drivers/i2c/busses/i2c-amd8111.c @@ -69,7 +69,7 @@ static struct pci_driver amd8111_driver;   * ACPI 2.0 chapter 13 access of registers of the EC   */ -static unsigned int amd_ec_wait_write(struct amd_smbus *smbus) +static int amd_ec_wait_write(struct amd_smbus *smbus)  {  	int timeout = 500; @@ -85,7 +85,7 @@ static unsigned int amd_ec_wait_write(struct amd_smbus *smbus)  	return 0;  } -static unsigned int amd_ec_wait_read(struct amd_smbus *smbus) +static int amd_ec_wait_read(struct amd_smbus *smbus)  {  	int timeout = 500; @@ -101,7 +101,7 @@ static unsigned int amd_ec_wait_read(struct amd_smbus *smbus)  	return 0;  } -static unsigned int amd_ec_read(struct amd_smbus *smbus, unsigned char address, +static int amd_ec_read(struct amd_smbus *smbus, unsigned char address,  		unsigned char *data)  {  	int status; @@ -124,7 +124,7 @@ static unsigned int amd_ec_read(struct amd_smbus *smbus, unsigned char address,  	return 0;  } -static unsigned int amd_ec_write(struct amd_smbus *smbus, unsigned char address, +static int amd_ec_write(struct amd_smbus *smbus, unsigned char address,  		unsigned char data)  {  	int status; @@ -196,7 +196,7 @@ static s32 amd8111_access(struct i2c_adapter * adap, u16 addr,  {  	struct amd_smbus *smbus = adap->algo_data;  	unsigned char protocol, len, pec, temp[2]; -	int i; +	int i, status;  	protocol = (read_write == I2C_SMBUS_READ) ? AMD_SMB_PRTCL_READ  						  : AMD_SMB_PRTCL_WRITE; @@ -209,38 +209,62 @@ static s32 amd8111_access(struct i2c_adapter * adap, u16 addr,  			break;  		case I2C_SMBUS_BYTE: -			if (read_write == I2C_SMBUS_WRITE) -				amd_ec_write(smbus, AMD_SMB_CMD, command); +			if (read_write == I2C_SMBUS_WRITE) { +				status = amd_ec_write(smbus, AMD_SMB_CMD, +						      command); +				if (status) +					return status; +			}  			protocol |= AMD_SMB_PRTCL_BYTE;  			break;  		case I2C_SMBUS_BYTE_DATA: -			amd_ec_write(smbus, AMD_SMB_CMD, command); -			if (read_write == I2C_SMBUS_WRITE) -				amd_ec_write(smbus, AMD_SMB_DATA, data->byte); +			status = amd_ec_write(smbus, AMD_SMB_CMD, command); +			if (status) +				return status; +			if (read_write == I2C_SMBUS_WRITE) { +				status = amd_ec_write(smbus, AMD_SMB_DATA, +						      data->byte); +				if (status) +					return status; +			}  			protocol |= AMD_SMB_PRTCL_BYTE_DATA;  			break;  		case I2C_SMBUS_WORD_DATA: -			amd_ec_write(smbus, AMD_SMB_CMD, command); +			status = amd_ec_write(smbus, AMD_SMB_CMD, command); +			if (status) +				return status;  			if (read_write == I2C_SMBUS_WRITE) { -				amd_ec_write(smbus, AMD_SMB_DATA, -					     data->word & 0xff); -				amd_ec_write(smbus, AMD_SMB_DATA + 1, -					     data->word >> 8); +				status = amd_ec_write(smbus, AMD_SMB_DATA, +						      data->word & 0xff); +				if (status) +					return status; +				status = amd_ec_write(smbus, AMD_SMB_DATA + 1, +						      data->word >> 8); +				if (status) +					return status;  			}  			protocol |= AMD_SMB_PRTCL_WORD_DATA | pec;  			break;  		case I2C_SMBUS_BLOCK_DATA: -			amd_ec_write(smbus, AMD_SMB_CMD, command); +			status = amd_ec_write(smbus, AMD_SMB_CMD, command); +			if (status) +				return status;  			if (read_write == I2C_SMBUS_WRITE) {  				len = min_t(u8, data->block[0],  					    I2C_SMBUS_BLOCK_MAX); -				amd_ec_write(smbus, AMD_SMB_BCNT, len); -				for (i = 0; i < len; i++) -					amd_ec_write(smbus, AMD_SMB_DATA + i, -						     data->block[i + 1]); +				status = amd_ec_write(smbus, AMD_SMB_BCNT, len); +				if (status) +					return status; +				for (i = 0; i < len; i++) { +					status = +					  amd_ec_write(smbus, AMD_SMB_DATA + i, +						       data->block[i + 1]); +					if (status) +						return status; +				}  			}  			protocol |= AMD_SMB_PRTCL_BLOCK_DATA | pec;  			break; @@ -248,19 +272,35 @@ static s32 amd8111_access(struct i2c_adapter * adap, u16 addr,  		case I2C_SMBUS_I2C_BLOCK_DATA:  			len = min_t(u8, data->block[0],  				    I2C_SMBUS_BLOCK_MAX); -			amd_ec_write(smbus, AMD_SMB_CMD, command); -			amd_ec_write(smbus, AMD_SMB_BCNT, len); +			status = amd_ec_write(smbus, AMD_SMB_CMD, command); +			if (status) +				return status; +			status = amd_ec_write(smbus, AMD_SMB_BCNT, len); +			if (status) +				return status;  			if (read_write == I2C_SMBUS_WRITE) -				for (i = 0; i < len; i++) -					amd_ec_write(smbus, AMD_SMB_DATA + i, -						     data->block[i + 1]); +				for (i = 0; i < len; i++) { +					status = +					  amd_ec_write(smbus, AMD_SMB_DATA + i, +						       data->block[i + 1]); +					if (status) +						return status; +				}  			protocol |= AMD_SMB_PRTCL_I2C_BLOCK_DATA;  			break;  		case I2C_SMBUS_PROC_CALL: -			amd_ec_write(smbus, AMD_SMB_CMD, command); -			amd_ec_write(smbus, AMD_SMB_DATA, data->word & 0xff); -			amd_ec_write(smbus, AMD_SMB_DATA + 1, data->word >> 8); +			status = amd_ec_write(smbus, AMD_SMB_CMD, command); +			if (status) +				return status; +			status = amd_ec_write(smbus, AMD_SMB_DATA, +					      data->word & 0xff); +			if (status) +				return status; +			status = amd_ec_write(smbus, AMD_SMB_DATA + 1, +					      data->word >> 8); +			if (status) +				return status;  			protocol = AMD_SMB_PRTCL_PROC_CALL | pec;  			read_write = I2C_SMBUS_READ;  			break; @@ -268,11 +308,18 @@ static s32 amd8111_access(struct i2c_adapter * adap, u16 addr,  		case I2C_SMBUS_BLOCK_PROC_CALL:  			len = min_t(u8, data->block[0],  				    I2C_SMBUS_BLOCK_MAX - 1); -			amd_ec_write(smbus, AMD_SMB_CMD, command); -			amd_ec_write(smbus, AMD_SMB_BCNT, len); -			for (i = 0; i < len; i++) -				amd_ec_write(smbus, AMD_SMB_DATA + i, -					     data->block[i + 1]); +			status = amd_ec_write(smbus, AMD_SMB_CMD, command); +			if (status) +				return status; +			status = amd_ec_write(smbus, AMD_SMB_BCNT, len); +			if (status) +				return status; +			for (i = 0; i < len; i++) { +				status = amd_ec_write(smbus, AMD_SMB_DATA + i, +						      data->block[i + 1]); +				if (status) +					return status; +			}  			protocol = AMD_SMB_PRTCL_BLOCK_PROC_CALL | pec;  			read_write = I2C_SMBUS_READ;  			break; @@ -282,24 +329,29 @@ static s32 amd8111_access(struct i2c_adapter * adap, u16 addr,  			return -EOPNOTSUPP;  	} -	amd_ec_write(smbus, AMD_SMB_ADDR, addr << 1); -	amd_ec_write(smbus, AMD_SMB_PRTCL, protocol); +	status = amd_ec_write(smbus, AMD_SMB_ADDR, addr << 1); +	if (status) +		return status; +	status = amd_ec_write(smbus, AMD_SMB_PRTCL, protocol); +	if (status) +		return status; -	/* FIXME this discards status from ec_read(); so temp[0] will -	 * hold stack garbage ... the rest of this routine will act -	 * nonsensically.  Ignored ec_write() status might explain -	 * some such failures... -	 */ -	amd_ec_read(smbus, AMD_SMB_STS, temp + 0); +	status = amd_ec_read(smbus, AMD_SMB_STS, temp + 0); +	if (status) +		return status;  	if (~temp[0] & AMD_SMB_STS_DONE) {  		udelay(500); -		amd_ec_read(smbus, AMD_SMB_STS, temp + 0); +		status = amd_ec_read(smbus, AMD_SMB_STS, temp + 0); +		if (status) +			return status;  	}  	if (~temp[0] & AMD_SMB_STS_DONE) {  		msleep(1); -		amd_ec_read(smbus, AMD_SMB_STS, temp + 0); +		status = amd_ec_read(smbus, AMD_SMB_STS, temp + 0); +		if (status) +			return status;  	}  	if ((~temp[0] & AMD_SMB_STS_DONE) || (temp[0] & AMD_SMB_STS_STATUS)) @@ -311,24 +363,35 @@ static s32 amd8111_access(struct i2c_adapter * adap, u16 addr,  	switch (size) {  		case I2C_SMBUS_BYTE:  		case I2C_SMBUS_BYTE_DATA: -			amd_ec_read(smbus, AMD_SMB_DATA, &data->byte); +			status = amd_ec_read(smbus, AMD_SMB_DATA, &data->byte); +			if (status) +				return status;  			break;  		case I2C_SMBUS_WORD_DATA:  		case I2C_SMBUS_PROC_CALL: -			amd_ec_read(smbus, AMD_SMB_DATA, temp + 0); -			amd_ec_read(smbus, AMD_SMB_DATA + 1, temp + 1); +			status = amd_ec_read(smbus, AMD_SMB_DATA, temp + 0); +			if (status) +				return status; +			status = amd_ec_read(smbus, AMD_SMB_DATA + 1, temp + 1); +			if (status) +				return status;  			data->word = (temp[1] << 8) | temp[0];  			break;  		case I2C_SMBUS_BLOCK_DATA:  		case I2C_SMBUS_BLOCK_PROC_CALL: -			amd_ec_read(smbus, AMD_SMB_BCNT, &len); +			status = amd_ec_read(smbus, AMD_SMB_BCNT, &len); +			if (status) +				return status;  			len = min_t(u8, len, I2C_SMBUS_BLOCK_MAX);  		case I2C_SMBUS_I2C_BLOCK_DATA: -			for (i = 0; i < len; i++) -				amd_ec_read(smbus, AMD_SMB_DATA + i, -					    data->block + i + 1); +			for (i = 0; i < len; i++) { +				status = amd_ec_read(smbus, AMD_SMB_DATA + i, +						     data->block + i + 1); +				if (status) +					return status; +			}  			data->block[0] = len;  			break;  	} diff --git a/drivers/i2c/busses/i2c-cpm.c b/drivers/i2c/busses/i2c-cpm.c index b02b4533651..f2de3be35df 100644 --- a/drivers/i2c/busses/i2c-cpm.c +++ b/drivers/i2c/busses/i2c-cpm.c @@ -105,7 +105,7 @@ struct i2c_reg {  struct cpm_i2c {  	char *base; -	struct of_device *ofdev; +	struct platform_device *ofdev;  	struct i2c_adapter adap;  	uint dp_addr;  	int version; /* CPM1=1, CPM2=2 */ @@ -428,7 +428,7 @@ static const struct i2c_adapter cpm_ops = {  static int __devinit cpm_i2c_setup(struct cpm_i2c *cpm)  { -	struct of_device *ofdev = cpm->ofdev; +	struct platform_device *ofdev = cpm->ofdev;  	const u32 *data;  	int len, ret, i;  	void __iomem *i2c_base; @@ -634,7 +634,7 @@ static void cpm_i2c_shutdown(struct cpm_i2c *cpm)  		cpm_muram_free(cpm->i2c_addr);  } -static int __devinit cpm_i2c_probe(struct of_device *ofdev, +static int __devinit cpm_i2c_probe(struct platform_device *ofdev,  			 const struct of_device_id *match)  {  	int result, len; @@ -652,6 +652,7 @@ static int __devinit cpm_i2c_probe(struct of_device *ofdev,  	cpm->adap = cpm_ops;  	i2c_set_adapdata(&cpm->adap, cpm);  	cpm->adap.dev.parent = &ofdev->dev; +	cpm->adap.dev.of_node = of_node_get(ofdev->dev.of_node);  	result = cpm_i2c_setup(cpm);  	if (result) { @@ -679,7 +680,7 @@ static int __devinit cpm_i2c_probe(struct of_device *ofdev,  	/*  	 * register OF I2C devices  	 */ -	of_register_i2c_devices(&cpm->adap, ofdev->dev.of_node); +	of_i2c_register_devices(&cpm->adap);  	return 0;  out_shut: @@ -691,7 +692,7 @@ out_free:  	return result;  } -static int __devexit cpm_i2c_remove(struct of_device *ofdev) +static int __devexit cpm_i2c_remove(struct platform_device *ofdev)  {  	struct cpm_i2c *cpm = dev_get_drvdata(&ofdev->dev); diff --git a/drivers/i2c/busses/i2c-davinci.c b/drivers/i2c/busses/i2c-davinci.c index 4523364e672..5795c8398c7 100644 --- a/drivers/i2c/busses/i2c-davinci.c +++ b/drivers/i2c/busses/i2c-davinci.c @@ -36,14 +36,16 @@  #include <linux/platform_device.h>  #include <linux/io.h>  #include <linux/slab.h> +#include <linux/cpufreq.h> +#include <linux/gpio.h>  #include <mach/hardware.h> -  #include <mach/i2c.h>  /* ----- global defines ----------------------------------------------- */  #define DAVINCI_I2C_TIMEOUT	(1*HZ) +#define DAVINCI_I2C_MAX_TRIES	2  #define I2C_DAVINCI_INTR_ALL    (DAVINCI_I2C_IMR_AAS | \  				 DAVINCI_I2C_IMR_SCD | \  				 DAVINCI_I2C_IMR_ARDY | \ @@ -72,37 +74,29 @@  #define DAVINCI_I2C_IVR_NACK	0x02  #define DAVINCI_I2C_IVR_AL	0x01 -#define DAVINCI_I2C_STR_BB	(1 << 12) -#define DAVINCI_I2C_STR_RSFULL	(1 << 11) -#define DAVINCI_I2C_STR_SCD	(1 << 5) -#define DAVINCI_I2C_STR_ARDY	(1 << 2) -#define DAVINCI_I2C_STR_NACK	(1 << 1) -#define DAVINCI_I2C_STR_AL	(1 << 0) - -#define DAVINCI_I2C_MDR_NACK	(1 << 15) -#define DAVINCI_I2C_MDR_STT	(1 << 13) -#define DAVINCI_I2C_MDR_STP	(1 << 11) -#define DAVINCI_I2C_MDR_MST	(1 << 10) -#define DAVINCI_I2C_MDR_TRX	(1 << 9) -#define DAVINCI_I2C_MDR_XA	(1 << 8) -#define DAVINCI_I2C_MDR_RM	(1 << 7) -#define DAVINCI_I2C_MDR_IRS	(1 << 5) - -#define DAVINCI_I2C_IMR_AAS	(1 << 6) -#define DAVINCI_I2C_IMR_SCD	(1 << 5) -#define DAVINCI_I2C_IMR_XRDY	(1 << 4) -#define DAVINCI_I2C_IMR_RRDY	(1 << 3) -#define DAVINCI_I2C_IMR_ARDY	(1 << 2) -#define DAVINCI_I2C_IMR_NACK	(1 << 1) -#define DAVINCI_I2C_IMR_AL	(1 << 0) - -#define MOD_REG_BIT(val, mask, set) do { \ -	if (set) { \ -		val |= mask; \ -	} else { \ -		val &= ~mask; \ -	} \ -} while (0) +#define DAVINCI_I2C_STR_BB	BIT(12) +#define DAVINCI_I2C_STR_RSFULL	BIT(11) +#define DAVINCI_I2C_STR_SCD	BIT(5) +#define DAVINCI_I2C_STR_ARDY	BIT(2) +#define DAVINCI_I2C_STR_NACK	BIT(1) +#define DAVINCI_I2C_STR_AL	BIT(0) + +#define DAVINCI_I2C_MDR_NACK	BIT(15) +#define DAVINCI_I2C_MDR_STT	BIT(13) +#define DAVINCI_I2C_MDR_STP	BIT(11) +#define DAVINCI_I2C_MDR_MST	BIT(10) +#define DAVINCI_I2C_MDR_TRX	BIT(9) +#define DAVINCI_I2C_MDR_XA	BIT(8) +#define DAVINCI_I2C_MDR_RM	BIT(7) +#define DAVINCI_I2C_MDR_IRS	BIT(5) + +#define DAVINCI_I2C_IMR_AAS	BIT(6) +#define DAVINCI_I2C_IMR_SCD	BIT(5) +#define DAVINCI_I2C_IMR_XRDY	BIT(4) +#define DAVINCI_I2C_IMR_RRDY	BIT(3) +#define DAVINCI_I2C_IMR_ARDY	BIT(2) +#define DAVINCI_I2C_IMR_NACK	BIT(1) +#define DAVINCI_I2C_IMR_AL	BIT(0)  struct davinci_i2c_dev {  	struct device           *dev; @@ -113,8 +107,13 @@ struct davinci_i2c_dev {  	u8			*buf;  	size_t			buf_len;  	int			irq; +	int			stop;  	u8			terminate;  	struct i2c_adapter	adapter; +#ifdef CONFIG_CPU_FREQ +	struct completion	xfr_complete; +	struct notifier_block	freq_transition; +#endif  };  /* default platform data to use if not supplied in the platform_device */ @@ -134,12 +133,59 @@ static inline u16 davinci_i2c_read_reg(struct davinci_i2c_dev *i2c_dev, int reg)  	return __raw_readw(i2c_dev->base + reg);  } -/* - * This functions configures I2C and brings I2C out of reset. - * This function is called during I2C init function. This function - * also gets called if I2C encounters any errors. +/* Generate a pulse on the i2c clock pin. */ +static void generic_i2c_clock_pulse(unsigned int scl_pin) +{ +	u16 i; + +	if (scl_pin) { +		/* Send high and low on the SCL line */ +		for (i = 0; i < 9; i++) { +			gpio_set_value(scl_pin, 0); +			udelay(20); +			gpio_set_value(scl_pin, 1); +			udelay(20); +		} +	} +} + +/* This routine does i2c bus recovery as specified in the + * i2c protocol Rev. 03 section 3.16 titled "Bus clear"   */ -static int i2c_davinci_init(struct davinci_i2c_dev *dev) +static void i2c_recover_bus(struct davinci_i2c_dev *dev) +{ +	u32 flag = 0; +	struct davinci_i2c_platform_data *pdata = dev->dev->platform_data; + +	dev_err(dev->dev, "initiating i2c bus recovery\n"); +	/* Send NACK to the slave */ +	flag = davinci_i2c_read_reg(dev, DAVINCI_I2C_MDR_REG); +	flag |=  DAVINCI_I2C_MDR_NACK; +	/* write the data into mode register */ +	davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, flag); +	if (pdata) +		generic_i2c_clock_pulse(pdata->scl_pin); +	/* Send STOP */ +	flag = davinci_i2c_read_reg(dev, DAVINCI_I2C_MDR_REG); +	flag |= DAVINCI_I2C_MDR_STP; +	davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, flag); +} + +static inline void davinci_i2c_reset_ctrl(struct davinci_i2c_dev *i2c_dev, +								int val) +{ +	u16 w; + +	w = davinci_i2c_read_reg(i2c_dev, DAVINCI_I2C_MDR_REG); +	if (!val)	/* put I2C into reset */ +		w &= ~DAVINCI_I2C_MDR_IRS; +	else		/* take I2C out of reset */ +		w |= DAVINCI_I2C_MDR_IRS; + +	davinci_i2c_write_reg(i2c_dev, DAVINCI_I2C_MDR_REG, w); +} + +static void i2c_davinci_calc_clk_dividers(struct davinci_i2c_dev *dev)  {  	struct davinci_i2c_platform_data *pdata = dev->dev->platform_data;  	u16 psc; @@ -148,15 +194,6 @@ static int i2c_davinci_init(struct davinci_i2c_dev *dev)  	u32 clkh;  	u32 clkl;  	u32 input_clock = clk_get_rate(dev->clk); -	u16 w; - -	if (!pdata) -		pdata = &davinci_i2c_platform_data_default; - -	/* put I2C into reset */ -	w = davinci_i2c_read_reg(dev, DAVINCI_I2C_MDR_REG); -	MOD_REG_BIT(w, DAVINCI_I2C_MDR_IRS, 0); -	davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, w);  	/* NOTE: I2C Clock divider programming info  	 * As per I2C specs the following formulas provide prescaler @@ -188,12 +225,32 @@ static int i2c_davinci_init(struct davinci_i2c_dev *dev)  	davinci_i2c_write_reg(dev, DAVINCI_I2C_CLKH_REG, clkh);  	davinci_i2c_write_reg(dev, DAVINCI_I2C_CLKL_REG, clkl); +	dev_dbg(dev->dev, "input_clock = %d, CLK = %d\n", input_clock, clk); +} + +/* + * This function configures I2C and brings I2C out of reset. + * This function is called during I2C init function. This function + * also gets called if I2C encounters any errors. + */ +static int i2c_davinci_init(struct davinci_i2c_dev *dev) +{ +	struct davinci_i2c_platform_data *pdata = dev->dev->platform_data; + +	if (!pdata) +		pdata = &davinci_i2c_platform_data_default; + +	/* put I2C into reset */ +	davinci_i2c_reset_ctrl(dev, 0); + +	/* compute clock dividers */ +	i2c_davinci_calc_clk_dividers(dev); +  	/* Respond at reserved "SMBus Host" slave address" (and zero);  	 * we seem to have no option to not respond...  	 */  	davinci_i2c_write_reg(dev, DAVINCI_I2C_OAR_REG, 0x08); -	dev_dbg(dev->dev, "input_clock = %d, CLK = %d\n", input_clock, clk);  	dev_dbg(dev->dev, "PSC  = %d\n",  		davinci_i2c_read_reg(dev, DAVINCI_I2C_PSC_REG));  	dev_dbg(dev->dev, "CLKL = %d\n", @@ -204,9 +261,7 @@ static int i2c_davinci_init(struct davinci_i2c_dev *dev)  		pdata->bus_freq, pdata->bus_delay);  	/* Take the I2C module out of reset: */ -	w = davinci_i2c_read_reg(dev, DAVINCI_I2C_MDR_REG); -	MOD_REG_BIT(w, DAVINCI_I2C_MDR_IRS, 1); -	davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, w); +	davinci_i2c_reset_ctrl(dev, 1);  	/* Enable interrupts */  	davinci_i2c_write_reg(dev, DAVINCI_I2C_IMR_REG, I2C_DAVINCI_INTR_ALL); @@ -221,14 +276,22 @@ static int i2c_davinci_wait_bus_not_busy(struct davinci_i2c_dev *dev,  					 char allow_sleep)  {  	unsigned long timeout; +	static u16 to_cnt;  	timeout = jiffies + dev->adapter.timeout;  	while (davinci_i2c_read_reg(dev, DAVINCI_I2C_STR_REG)  	       & DAVINCI_I2C_STR_BB) { -		if (time_after(jiffies, timeout)) { -			dev_warn(dev->dev, -				 "timeout waiting for bus ready\n"); -			return -ETIMEDOUT; +		if (to_cnt <= DAVINCI_I2C_MAX_TRIES) { +			if (time_after(jiffies, timeout)) { +				dev_warn(dev->dev, +				"timeout waiting for bus ready\n"); +				to_cnt++; +				return -ETIMEDOUT; +			} else { +				to_cnt = 0; +				i2c_recover_bus(dev); +				i2c_davinci_init(dev); +			}  		}  		if (allow_sleep)  			schedule_timeout(1); @@ -250,9 +313,6 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop)  	u16 w;  	int r; -	if (msg->len == 0) -		return -EINVAL; -  	if (!pdata)  		pdata = &davinci_i2c_platform_data_default;  	/* Introduce a delay, required for some boards (e.g Davinci EVM) */ @@ -264,40 +324,64 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop)  	dev->buf = msg->buf;  	dev->buf_len = msg->len; +	dev->stop = stop;  	davinci_i2c_write_reg(dev, DAVINCI_I2C_CNT_REG, dev->buf_len);  	INIT_COMPLETION(dev->cmd_complete);  	dev->cmd_err = 0; -	/* Take I2C out of reset, configure it as master and set the -	 * start bit */ -	flag = DAVINCI_I2C_MDR_IRS | DAVINCI_I2C_MDR_MST | DAVINCI_I2C_MDR_STT; +	/* Take I2C out of reset and configure it as master */ +	flag = DAVINCI_I2C_MDR_IRS | DAVINCI_I2C_MDR_MST;  	/* if the slave address is ten bit address, enable XA bit */  	if (msg->flags & I2C_M_TEN)  		flag |= DAVINCI_I2C_MDR_XA;  	if (!(msg->flags & I2C_M_RD))  		flag |= DAVINCI_I2C_MDR_TRX; -	if (stop) -		flag |= DAVINCI_I2C_MDR_STP; +	if (msg->len == 0) +		flag |= DAVINCI_I2C_MDR_RM;  	/* Enable receive or transmit interrupts */  	w = davinci_i2c_read_reg(dev, DAVINCI_I2C_IMR_REG);  	if (msg->flags & I2C_M_RD) -		MOD_REG_BIT(w, DAVINCI_I2C_IMR_RRDY, 1); +		w |= DAVINCI_I2C_IMR_RRDY;  	else -		MOD_REG_BIT(w, DAVINCI_I2C_IMR_XRDY, 1); +		w |= DAVINCI_I2C_IMR_XRDY;  	davinci_i2c_write_reg(dev, DAVINCI_I2C_IMR_REG, w);  	dev->terminate = 0; -	/* write the data into mode register */ + +	/* +	 * Write mode register first as needed for correct behaviour +	 * on OMAP-L138, but don't set STT yet to avoid a race with XRDY +	 * occuring before we have loaded DXR +	 */ +	davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, flag); + +	/* +	 * First byte should be set here, not after interrupt, +	 * because transmit-data-ready interrupt can come before +	 * NACK-interrupt during sending of previous message and +	 * ICDXR may have wrong data +	 * It also saves us one interrupt, slightly faster +	 */ +	if ((!(msg->flags & I2C_M_RD)) && dev->buf_len) { +		davinci_i2c_write_reg(dev, DAVINCI_I2C_DXR_REG, *dev->buf++); +		dev->buf_len--; +	} + +	/* Set STT to begin transmit now DXR is loaded */ +	flag |= DAVINCI_I2C_MDR_STT; +	if (stop && msg->len != 0) +		flag |= DAVINCI_I2C_MDR_STP;  	davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, flag);  	r = wait_for_completion_interruptible_timeout(&dev->cmd_complete,  						      dev->adapter.timeout);  	if (r == 0) {  		dev_err(dev->dev, "controller timed out\n"); +		i2c_recover_bus(dev);  		i2c_davinci_init(dev);  		dev->buf_len = 0;  		return -ETIMEDOUT; @@ -334,7 +418,7 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop)  			return msg->len;  		if (stop) {  			w = davinci_i2c_read_reg(dev, DAVINCI_I2C_MDR_REG); -			MOD_REG_BIT(w, DAVINCI_I2C_MDR_STP, 1); +			w |= DAVINCI_I2C_MDR_STP;  			davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, w);  		}  		return -EREMOTEIO; @@ -367,12 +451,17 @@ i2c_davinci_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)  		if (ret < 0)  			return ret;  	} + +#ifdef CONFIG_CPU_FREQ +	complete(&dev->xfr_complete); +#endif +  	return num;  }  static u32 i2c_davinci_func(struct i2c_adapter *adap)  { -	return I2C_FUNC_I2C | (I2C_FUNC_SMBUS_EMUL & ~I2C_FUNC_SMBUS_QUICK); +	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;  }  static void terminate_read(struct davinci_i2c_dev *dev) @@ -431,6 +520,14 @@ static irqreturn_t i2c_davinci_isr(int this_irq, void *dev_id)  		case DAVINCI_I2C_IVR_ARDY:  			davinci_i2c_write_reg(dev,  				DAVINCI_I2C_STR_REG, DAVINCI_I2C_STR_ARDY); +			if (((dev->buf_len == 0) && (dev->stop != 0)) || +			    (dev->cmd_err & DAVINCI_I2C_STR_NACK)) { +				w = davinci_i2c_read_reg(dev, +							 DAVINCI_I2C_MDR_REG); +				w |= DAVINCI_I2C_MDR_STP; +				davinci_i2c_write_reg(dev, +						      DAVINCI_I2C_MDR_REG, w); +			}  			complete(&dev->cmd_complete);  			break; @@ -462,7 +559,7 @@ static irqreturn_t i2c_davinci_isr(int this_irq, void *dev_id)  				w = davinci_i2c_read_reg(dev,  							 DAVINCI_I2C_IMR_REG); -				MOD_REG_BIT(w, DAVINCI_I2C_IMR_XRDY, 0); +				w &= ~DAVINCI_I2C_IMR_XRDY;  				davinci_i2c_write_reg(dev,  						      DAVINCI_I2C_IMR_REG,  						      w); @@ -491,6 +588,48 @@ static irqreturn_t i2c_davinci_isr(int this_irq, void *dev_id)  	return count ? IRQ_HANDLED : IRQ_NONE;  } +#ifdef CONFIG_CPU_FREQ +static int i2c_davinci_cpufreq_transition(struct notifier_block *nb, +				     unsigned long val, void *data) +{ +	struct davinci_i2c_dev *dev; + +	dev = container_of(nb, struct davinci_i2c_dev, freq_transition); +	if (val == CPUFREQ_PRECHANGE) { +		wait_for_completion(&dev->xfr_complete); +		davinci_i2c_reset_ctrl(dev, 0); +	} else if (val == CPUFREQ_POSTCHANGE) { +		i2c_davinci_calc_clk_dividers(dev); +		davinci_i2c_reset_ctrl(dev, 1); +	} + +	return 0; +} + +static inline int i2c_davinci_cpufreq_register(struct davinci_i2c_dev *dev) +{ +	dev->freq_transition.notifier_call = i2c_davinci_cpufreq_transition; + +	return cpufreq_register_notifier(&dev->freq_transition, +					 CPUFREQ_TRANSITION_NOTIFIER); +} + +static inline void i2c_davinci_cpufreq_deregister(struct davinci_i2c_dev *dev) +{ +	cpufreq_unregister_notifier(&dev->freq_transition, +				    CPUFREQ_TRANSITION_NOTIFIER); +} +#else +static inline int i2c_davinci_cpufreq_register(struct davinci_i2c_dev *dev) +{ +	return 0; +} + +static inline void i2c_davinci_cpufreq_deregister(struct davinci_i2c_dev *dev) +{ +} +#endif +  static struct i2c_algorithm i2c_davinci_algo = {  	.master_xfer	= i2c_davinci_xfer,  	.functionality	= i2c_davinci_func, @@ -530,6 +669,9 @@ static int davinci_i2c_probe(struct platform_device *pdev)  	}  	init_completion(&dev->cmd_complete); +#ifdef CONFIG_CPU_FREQ +	init_completion(&dev->xfr_complete); +#endif  	dev->dev = get_device(&pdev->dev);  	dev->irq = irq->start;  	platform_set_drvdata(pdev, dev); @@ -541,7 +683,12 @@ static int davinci_i2c_probe(struct platform_device *pdev)  	}  	clk_enable(dev->clk); -	dev->base = (void __iomem *)IO_ADDRESS(mem->start); +	dev->base = ioremap(mem->start, resource_size(mem)); +	if (!dev->base) { +		r = -EBUSY; +		goto err_mem_ioremap; +	} +  	i2c_davinci_init(dev);  	r = request_irq(dev->irq, i2c_davinci_isr, 0, pdev->name, dev); @@ -550,6 +697,12 @@ static int davinci_i2c_probe(struct platform_device *pdev)  		goto err_unuse_clocks;  	} +	r = i2c_davinci_cpufreq_register(dev); +	if (r) { +		dev_err(&pdev->dev, "failed to register cpufreq\n"); +		goto err_free_irq; +	} +  	adap = &dev->adapter;  	i2c_set_adapdata(adap, dev);  	adap->owner = THIS_MODULE; @@ -571,6 +724,8 @@ static int davinci_i2c_probe(struct platform_device *pdev)  err_free_irq:  	free_irq(dev->irq, dev);  err_unuse_clocks: +	iounmap(dev->base); +err_mem_ioremap:  	clk_disable(dev->clk);  	clk_put(dev->clk);  	dev->clk = NULL; @@ -589,6 +744,8 @@ static int davinci_i2c_remove(struct platform_device *pdev)  	struct davinci_i2c_dev *dev = platform_get_drvdata(pdev);  	struct resource *mem; +	i2c_davinci_cpufreq_deregister(dev); +  	platform_set_drvdata(pdev, NULL);  	i2c_del_adapter(&dev->adapter);  	put_device(&pdev->dev); @@ -599,6 +756,7 @@ static int davinci_i2c_remove(struct platform_device *pdev)  	davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, 0);  	free_irq(IRQ_I2C, dev); +	iounmap(dev->base);  	kfree(dev);  	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); @@ -606,6 +764,41 @@ static int davinci_i2c_remove(struct platform_device *pdev)  	return 0;  } +#ifdef CONFIG_PM +static int davinci_i2c_suspend(struct device *dev) +{ +	struct platform_device *pdev = to_platform_device(dev); +	struct davinci_i2c_dev *i2c_dev = platform_get_drvdata(pdev); + +	/* put I2C into reset */ +	davinci_i2c_reset_ctrl(i2c_dev, 0); +	clk_disable(i2c_dev->clk); + +	return 0; +} + +static int davinci_i2c_resume(struct device *dev) +{ +	struct platform_device *pdev = to_platform_device(dev); +	struct davinci_i2c_dev *i2c_dev = platform_get_drvdata(pdev); + +	clk_enable(i2c_dev->clk); +	/* take I2C out of reset */ +	davinci_i2c_reset_ctrl(i2c_dev, 1); + +	return 0; +} + +static const struct dev_pm_ops davinci_i2c_pm = { +	.suspend        = davinci_i2c_suspend, +	.resume         = davinci_i2c_resume, +}; + +#define davinci_i2c_pm_ops (&davinci_i2c_pm) +#else +#define davinci_i2c_pm_ops NULL +#endif +  /* work with hotplug and coldplug */  MODULE_ALIAS("platform:i2c_davinci"); @@ -615,6 +808,7 @@ static struct platform_driver davinci_i2c_driver = {  	.driver		= {  		.name	= "i2c_davinci",  		.owner	= THIS_MODULE, +		.pm	= davinci_i2c_pm_ops,  	},  }; diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index c60081169cc..59d65981eed 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c @@ -38,10 +38,10 @@    82801G   (ICH7)       0x27da     32     hard     yes     yes     yes    82801H   (ICH8)       0x283e     32     hard     yes     yes     yes    82801I   (ICH9)       0x2930     32     hard     yes     yes     yes -  Tolapai               0x5032     32     hard     yes     yes     yes +  EP80579 (Tolapai)     0x5032     32     hard     yes     yes     yes    ICH10                 0x3a30     32     hard     yes     yes     yes    ICH10                 0x3a60     32     hard     yes     yes     yes -  3400/5 Series (PCH)   0x3b30     32     hard     yes     yes     yes +  5/3400 Series (PCH)   0x3b30     32     hard     yes     yes     yes    Cougar Point (PCH)    0x1c22     32     hard     yes     yes     yes    Features supported by this driver: @@ -587,11 +587,11 @@ static const struct pci_device_id i801_ids[] = {  	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB2_17) },  	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_5) },  	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH9_6) }, -	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_TOLAPAI_1) }, +	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_EP80579_1) },  	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH10_4) },  	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH10_5) }, -	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PCH_SMBUS) }, -	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CPT_SMBUS) }, +	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_5_3400_SERIES_SMBUS) }, +	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_COUGARPOINT_SMBUS) },  	{ 0, }  }; diff --git a/drivers/i2c/busses/i2c-ibm_iic.c b/drivers/i2c/busses/i2c-ibm_iic.c index bf344135647..6e3c3824033 100644 --- a/drivers/i2c/busses/i2c-ibm_iic.c +++ b/drivers/i2c/busses/i2c-ibm_iic.c @@ -41,7 +41,6 @@  #include <asm/irq.h>  #include <linux/io.h>  #include <linux/i2c.h> -#include <linux/i2c-id.h>  #include <linux/of_platform.h>  #include <linux/of_i2c.h> @@ -661,7 +660,7 @@ static inline u8 iic_clckdiv(unsigned int opb)  	return (u8)((opb + 9) / 10 - 1);  } -static int __devinit iic_request_irq(struct of_device *ofdev, +static int __devinit iic_request_irq(struct platform_device *ofdev,  				     struct ibm_iic_private *dev)  {  	struct device_node *np = ofdev->dev.of_node; @@ -692,7 +691,7 @@ static int __devinit iic_request_irq(struct of_device *ofdev,  /*   * Register single IIC interface   */ -static int __devinit iic_probe(struct of_device *ofdev, +static int __devinit iic_probe(struct platform_device *ofdev,  			       const struct of_device_id *match)  {  	struct device_node *np = ofdev->dev.of_node; @@ -745,6 +744,7 @@ static int __devinit iic_probe(struct of_device *ofdev,  	/* Register it with i2c layer */  	adap = &dev->adap;  	adap->dev.parent = &ofdev->dev; +	adap->dev.of_node = of_node_get(np);  	strlcpy(adap->name, "IBM IIC", sizeof(adap->name));  	i2c_set_adapdata(adap, dev);  	adap->class = I2C_CLASS_HWMON | I2C_CLASS_SPD; @@ -761,7 +761,7 @@ static int __devinit iic_probe(struct of_device *ofdev,  		 dev->fast_mode ? "fast (400 kHz)" : "standard (100 kHz)");  	/* Now register all the child nodes */ -	of_register_i2c_devices(adap, np); +	of_i2c_register_devices(adap);  	return 0; @@ -782,7 +782,7 @@ error_cleanup:  /*   * Cleanup initialized IIC interface   */ -static int __devexit iic_remove(struct of_device *ofdev) +static int __devexit iic_remove(struct platform_device *ofdev)  {  	struct ibm_iic_private *dev = dev_get_drvdata(&ofdev->dev); diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c index d1ff9408dc1..4c2a62b75b5 100644 --- a/drivers/i2c/busses/i2c-imx.c +++ b/drivers/i2c/busses/i2c-imx.c @@ -159,15 +159,9 @@ static int i2c_imx_bus_busy(struct imx_i2c_struct *i2c_imx, int for_busy)  static int i2c_imx_trx_complete(struct imx_i2c_struct *i2c_imx)  { -	int result; - -	result = wait_event_interruptible_timeout(i2c_imx->queue, -		i2c_imx->i2csr & I2SR_IIF, HZ / 10); +	wait_event_timeout(i2c_imx->queue, i2c_imx->i2csr & I2SR_IIF, HZ / 10); -	if (unlikely(result < 0)) { -		dev_dbg(&i2c_imx->adapter.dev, "<%s> result < 0\n", __func__); -		return result; -	} else if (unlikely(!(i2c_imx->i2csr & I2SR_IIF))) { +	if (unlikely(!(i2c_imx->i2csr & I2SR_IIF))) {  		dev_dbg(&i2c_imx->adapter.dev, "<%s> Timeout\n", __func__);  		return -ETIMEDOUT;  	} @@ -295,7 +289,7 @@ static irqreturn_t i2c_imx_isr(int irq, void *dev_id)  		i2c_imx->i2csr = temp;  		temp &= ~I2SR_IIF;  		writeb(temp, i2c_imx->base + IMX_I2C_I2SR); -		wake_up_interruptible(&i2c_imx->queue); +		wake_up(&i2c_imx->queue);  		return IRQ_HANDLED;  	} diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c index df00eb1f11f..b74e6dc6886 100644 --- a/drivers/i2c/busses/i2c-mpc.c +++ b/drivers/i2c/busses/i2c-mpc.c @@ -63,6 +63,7 @@ struct mpc_i2c {  	wait_queue_head_t queue;  	struct i2c_adapter adap;  	int irq; +	u32 real_clk;  };  struct mpc_i2c_divider { @@ -96,20 +97,23 @@ static irqreturn_t mpc_i2c_isr(int irq, void *dev_id)  /* Sometimes 9th clock pulse isn't generated, and slave doesn't release   * the bus, because it wants to send ACK.   * Following sequence of enabling/disabling and sending start/stop generates - * the pulse, so it's all OK. + * the 9 pulses, so it's all OK.   */  static void mpc_i2c_fixup(struct mpc_i2c *i2c)  { -	writeccr(i2c, 0); -	udelay(30); -	writeccr(i2c, CCR_MEN); -	udelay(30); -	writeccr(i2c, CCR_MSTA | CCR_MTX); -	udelay(30); -	writeccr(i2c, CCR_MSTA | CCR_MTX | CCR_MEN); -	udelay(30); -	writeccr(i2c, CCR_MEN); -	udelay(30); +	int k; +	u32 delay_val = 1000000 / i2c->real_clk + 1; + +	if (delay_val < 2) +		delay_val = 2; + +	for (k = 9; k; k--) { +		writeccr(i2c, 0); +		writeccr(i2c, CCR_MSTA | CCR_MTX | CCR_MEN); +		udelay(delay_val); +		writeccr(i2c, CCR_MEN); +		udelay(delay_val << 1); +	}  }  static int i2c_wait(struct mpc_i2c *i2c, unsigned timeout, int writing) @@ -190,15 +194,18 @@ static const struct mpc_i2c_divider mpc_i2c_dividers_52xx[] __devinitconst = {  };  static int __devinit mpc_i2c_get_fdr_52xx(struct device_node *node, u32 clock, -					  int prescaler) +					  int prescaler, u32 *real_clk)  {  	const struct mpc_i2c_divider *div = NULL;  	unsigned int pvr = mfspr(SPRN_PVR);  	u32 divider;  	int i; -	if (clock == MPC_I2C_CLOCK_LEGACY) +	if (clock == MPC_I2C_CLOCK_LEGACY) { +		/* see below - default fdr = 0x3f -> div = 2048 */ +		*real_clk = mpc5xxx_get_bus_frequency(node) / 2048;  		return -EINVAL; +	}  	/* Determine divider value */  	divider = mpc5xxx_get_bus_frequency(node) / clock; @@ -216,7 +223,8 @@ static int __devinit mpc_i2c_get_fdr_52xx(struct device_node *node, u32 clock,  			break;  	} -	return div ? (int)div->fdr : -EINVAL; +	*real_clk = mpc5xxx_get_bus_frequency(node) / div->divider; +	return (int)div->fdr;  }  static void __devinit mpc_i2c_setup_52xx(struct device_node *node, @@ -231,13 +239,14 @@ static void __devinit mpc_i2c_setup_52xx(struct device_node *node,  		return;  	} -	ret = mpc_i2c_get_fdr_52xx(node, clock, prescaler); +	ret = mpc_i2c_get_fdr_52xx(node, clock, prescaler, &i2c->real_clk);  	fdr = (ret >= 0) ? ret : 0x3f; /* backward compatibility */  	writeb(fdr & 0xff, i2c->base + MPC_I2C_FDR);  	if (ret >= 0) -		dev_info(i2c->dev, "clock %d Hz (fdr=%d)\n", clock, fdr); +		dev_info(i2c->dev, "clock %u Hz (fdr=%d)\n", i2c->real_clk, +			 fdr);  }  #else /* !(CONFIG_PPC_MPC52xx || CONFIG_PPC_MPC512x) */  static void __devinit mpc_i2c_setup_52xx(struct device_node *node, @@ -334,14 +343,17 @@ static u32 __devinit mpc_i2c_get_sec_cfg_8xxx(void)  }  static int __devinit mpc_i2c_get_fdr_8xxx(struct device_node *node, u32 clock, -					  u32 prescaler) +					  u32 prescaler, u32 *real_clk)  {  	const struct mpc_i2c_divider *div = NULL;  	u32 divider;  	int i; -	if (clock == MPC_I2C_CLOCK_LEGACY) +	if (clock == MPC_I2C_CLOCK_LEGACY) { +		/* see below - default fdr = 0x1031 -> div = 16 * 3072 */ +		*real_clk = fsl_get_sys_freq() / prescaler / (16 * 3072);  		return -EINVAL; +	}  	/* Determine proper divider value */  	if (of_device_is_compatible(node, "fsl,mpc8544-i2c")) @@ -364,6 +376,7 @@ static int __devinit mpc_i2c_get_fdr_8xxx(struct device_node *node, u32 clock,  			break;  	} +	*real_clk = fsl_get_sys_freq() / prescaler / div->divider;  	return div ? (int)div->fdr : -EINVAL;  } @@ -380,7 +393,7 @@ static void __devinit mpc_i2c_setup_8xxx(struct device_node *node,  		return;  	} -	ret = mpc_i2c_get_fdr_8xxx(node, clock, prescaler); +	ret = mpc_i2c_get_fdr_8xxx(node, clock, prescaler, &i2c->real_clk);  	fdr = (ret >= 0) ? ret : 0x1031; /* backward compatibility */  	writeb(fdr & 0xff, i2c->base + MPC_I2C_FDR); @@ -388,7 +401,7 @@ static void __devinit mpc_i2c_setup_8xxx(struct device_node *node,  	if (ret >= 0)  		dev_info(i2c->dev, "clock %d Hz (dfsrr=%d fdr=%d)\n", -			 clock, fdr >> 8, fdr & 0xff); +			 i2c->real_clk, fdr >> 8, fdr & 0xff);  }  #else /* !CONFIG_FSL_SOC */ @@ -500,10 +513,14 @@ static int mpc_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)  			return -EINTR;  		}  		if (time_after(jiffies, orig_jiffies + HZ)) { +			u8 status = readb(i2c->base + MPC_I2C_SR); +  			dev_dbg(i2c->dev, "timeout\n"); -			if (readb(i2c->base + MPC_I2C_SR) == -			    (CSR_MCF | CSR_MBB | CSR_RXAK)) +			if ((status & (CSR_MCF | CSR_MBB | CSR_RXAK)) != 0) { +				writeb(status & ~CSR_MAL, +				       i2c->base + MPC_I2C_SR);  				mpc_i2c_fixup(i2c); +			}  			return -EIO;  		}  		schedule(); @@ -543,7 +560,7 @@ static struct i2c_adapter mpc_ops = {  	.timeout = HZ,  }; -static int __devinit fsl_i2c_probe(struct of_device *op, +static int __devinit fsl_i2c_probe(struct platform_device *op,  				   const struct of_device_id *match)  {  	struct mpc_i2c *i2c; @@ -595,18 +612,27 @@ static int __devinit fsl_i2c_probe(struct of_device *op,  			mpc_i2c_setup_8xxx(op->dev.of_node, i2c, clock, 0);  	} +	prop = of_get_property(op->dev.of_node, "fsl,timeout", &plen); +	if (prop && plen == sizeof(u32)) { +		mpc_ops.timeout = *prop * HZ / 1000000; +		if (mpc_ops.timeout < 5) +			mpc_ops.timeout = 5; +	} +	dev_info(i2c->dev, "timeout %u us\n", mpc_ops.timeout * 1000000 / HZ); +  	dev_set_drvdata(&op->dev, i2c);  	i2c->adap = mpc_ops;  	i2c_set_adapdata(&i2c->adap, i2c);  	i2c->adap.dev.parent = &op->dev; +	i2c->adap.dev.of_node = of_node_get(op->dev.of_node);  	result = i2c_add_adapter(&i2c->adap);  	if (result < 0) {  		dev_err(i2c->dev, "failed to add adapter\n");  		goto fail_add;  	} -	of_register_i2c_devices(&i2c->adap, op->dev.of_node); +	of_i2c_register_devices(&i2c->adap);  	return result; @@ -621,7 +647,7 @@ static int __devinit fsl_i2c_probe(struct of_device *op,  	return result;  }; -static int __devexit fsl_i2c_remove(struct of_device *op) +static int __devexit fsl_i2c_remove(struct platform_device *op)  {  	struct mpc_i2c *i2c = dev_get_drvdata(&op->dev); diff --git a/drivers/i2c/busses/i2c-nuc900.c b/drivers/i2c/busses/i2c-nuc900.c new file mode 100644 index 00000000000..72434263787 --- /dev/null +++ b/drivers/i2c/busses/i2c-nuc900.c @@ -0,0 +1,708 @@ +/* + * linux/drivers/i2c/busses/i2c-nuc900.c + * + * Copyright (c) 2010 Nuvoton technology corporation. + * + * This driver based on S3C2410 I2C driver of Ben Dooks <ben-Y5A6D6n0/KfQXOPxS62xeg@public.gmane.org>. + * Written by Wan ZongShun <mcuos.com-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation;version 2 of the License. + * + */ + +#include <linux/kernel.h> +#include <linux/module.h> + +#include <linux/i2c.h> +#include <linux/init.h> +#include <linux/time.h> +#include <linux/interrupt.h> +#include <linux/delay.h> +#include <linux/errno.h> +#include <linux/err.h> +#include <linux/platform_device.h> +#include <linux/clk.h> +#include <linux/cpufreq.h> +#include <linux/slab.h> +#include <linux/io.h> + +#include <mach/mfp.h> +#include <mach/i2c.h> + +/* nuc900 i2c registers offset */ + +#define CSR		0x00 +#define DIVIDER		0x04 +#define CMDR		0x08 +#define SWR		0x0C +#define RXR		0x10 +#define TXR		0x14 + +/* nuc900 i2c CSR register bits */ + +#define IRQEN		0x003 +#define I2CBUSY		0x400 +#define I2CSTART	0x018 +#define IRQFLAG		0x004 +#define ARBIT_LOST	0x200 +#define SLAVE_ACK	0x800 + +/* nuc900 i2c CMDR register bits */ + +#define I2C_CMD_START	0x10 +#define I2C_CMD_STOP	0x08 +#define I2C_CMD_READ	0x04 +#define I2C_CMD_WRITE	0x02 +#define I2C_CMD_NACK	0x01 + +/* i2c controller state */ + +enum nuc900_i2c_state { +	STATE_IDLE, +	STATE_START, +	STATE_READ, +	STATE_WRITE, +	STATE_STOP +}; + +/* i2c controller private data */ + +struct nuc900_i2c { +	spinlock_t		lock; +	wait_queue_head_t	wait; + +	struct i2c_msg		*msg; +	unsigned int		msg_num; +	unsigned int		msg_idx; +	unsigned int		msg_ptr; +	unsigned int		irq; + +	enum nuc900_i2c_state	state; + +	void __iomem		*regs; +	struct clk		*clk; +	struct device		*dev; +	struct resource		*ioarea; +	struct i2c_adapter	adap; +}; + +/* nuc900_i2c_master_complete + * + * complete the message and wake up the caller, using the given return code, + * or zero to mean ok. +*/ + +static inline void nuc900_i2c_master_complete(struct nuc900_i2c *i2c, int ret) +{ +	dev_dbg(i2c->dev, "master_complete %d\n", ret); + +	i2c->msg_ptr = 0; +	i2c->msg = NULL; +	i2c->msg_idx++; +	i2c->msg_num = 0; +	if (ret) +		i2c->msg_idx = ret; + +	wake_up(&i2c->wait); +} + +/* irq enable/disable functions */ + +static inline void nuc900_i2c_disable_irq(struct nuc900_i2c *i2c) +{ +	unsigned long tmp; + +	tmp = readl(i2c->regs + CSR); +	writel(tmp & ~IRQEN, i2c->regs + CSR); +} + +static inline void nuc900_i2c_enable_irq(struct nuc900_i2c *i2c) +{ +	unsigned long tmp; + +	tmp = readl(i2c->regs + CSR); +	writel(tmp | IRQEN, i2c->regs + CSR); +} + + +/* nuc900_i2c_message_start + * + * put the start of a message onto the bus +*/ + +static void nuc900_i2c_message_start(struct nuc900_i2c *i2c, +				      struct i2c_msg *msg) +{ +	unsigned int addr = (msg->addr & 0x7f) << 1; + +	if (msg->flags & I2C_M_RD) +		addr |= 0x1; +	writel(addr & 0xff, i2c->regs + TXR); +	writel(I2C_CMD_START | I2C_CMD_WRITE, i2c->regs + CMDR); +} + +static inline void nuc900_i2c_stop(struct nuc900_i2c *i2c, int ret) +{ + +	dev_dbg(i2c->dev, "STOP\n"); + +	/* stop the transfer */ +	i2c->state = STATE_STOP; +	writel(I2C_CMD_STOP, i2c->regs + CMDR); + +	nuc900_i2c_master_complete(i2c, ret); +	nuc900_i2c_disable_irq(i2c); +} + +/* helper functions to determine the current state in the set of + * messages we are sending +*/ + +/* is_lastmsg() + * + * returns TRUE if the current message is the last in the set +*/ + +static inline int is_lastmsg(struct nuc900_i2c *i2c) +{ +	return i2c->msg_idx >= (i2c->msg_num - 1); +} + +/* is_msglast + * + * returns TRUE if we this is the last byte in the current message +*/ + +static inline int is_msglast(struct nuc900_i2c *i2c) +{ +	return i2c->msg_ptr == i2c->msg->len-1; +} + +/* is_msgend + * + * returns TRUE if we reached the end of the current message +*/ + +static inline int is_msgend(struct nuc900_i2c *i2c) +{ +	return i2c->msg_ptr >= i2c->msg->len; +} + +/* i2c_nuc900_irq_nextbyte + * + * process an interrupt and work out what to do + */ + +static void i2c_nuc900_irq_nextbyte(struct nuc900_i2c *i2c, +							unsigned long iicstat) +{ +	unsigned char byte; + +	switch (i2c->state) { + +	case STATE_IDLE: +		dev_err(i2c->dev, "%s: called in STATE_IDLE\n", __func__); +		break; + +	case STATE_STOP: +		dev_err(i2c->dev, "%s: called in STATE_STOP\n", __func__); +		nuc900_i2c_disable_irq(i2c); +		break; + +	case STATE_START: +		/* last thing we did was send a start condition on the +		 * bus, or started a new i2c message +		 */ + +		if (iicstat & SLAVE_ACK && +		    !(i2c->msg->flags & I2C_M_IGNORE_NAK)) { +			/* ack was not received... */ + +			dev_dbg(i2c->dev, "ack was not received\n"); +			nuc900_i2c_stop(i2c, -ENXIO); +			break; +		} + +		if (i2c->msg->flags & I2C_M_RD) +			i2c->state = STATE_READ; +		else +			i2c->state = STATE_WRITE; + +		/* terminate the transfer if there is nothing to do +		 * as this is used by the i2c probe to find devices. +		*/ + +		if (is_lastmsg(i2c) && i2c->msg->len == 0) { +			nuc900_i2c_stop(i2c, 0); +			break; +		} + +		if (i2c->state == STATE_READ) +			goto prepare_read; + +		/* fall through to the write state, as we will need to +		 * send a byte as well +		*/ + +	case STATE_WRITE: +		/* we are writing data to the device... check for the +		 * end of the message, and if so, work out what to do +		 */ + +		if (!(i2c->msg->flags & I2C_M_IGNORE_NAK)) { +			if (iicstat & SLAVE_ACK) { +				dev_dbg(i2c->dev, "WRITE: No Ack\n"); + +				nuc900_i2c_stop(i2c, -ECONNREFUSED); +				break; +			} +		} + +retry_write: + +		if (!is_msgend(i2c)) { +			byte = i2c->msg->buf[i2c->msg_ptr++]; +			writeb(byte, i2c->regs + TXR); +			writel(I2C_CMD_WRITE, i2c->regs + CMDR); + +		} else if (!is_lastmsg(i2c)) { +			/* we need to go to the next i2c message */ + +			dev_dbg(i2c->dev, "WRITE: Next Message\n"); + +			i2c->msg_ptr = 0; +			i2c->msg_idx++; +			i2c->msg++; + +			/* check to see if we need to do another message */ +			if (i2c->msg->flags & I2C_M_NOSTART) { + +				if (i2c->msg->flags & I2C_M_RD) { +					/* cannot do this, the controller +					 * forces us to send a new START +					 * when we change direction +					*/ + +					nuc900_i2c_stop(i2c, -EINVAL); +				} + +				goto retry_write; +			} else { +				/* send the new start */ +				nuc900_i2c_message_start(i2c, i2c->msg); +				i2c->state = STATE_START; +			} + +		} else { +			/* send stop */ + +			nuc900_i2c_stop(i2c, 0); +		} +		break; + +	case STATE_READ: +		/* we have a byte of data in the data register, do +		 * something with it, and then work out wether we are +		 * going to do any more read/write +		 */ + +		byte = readb(i2c->regs + RXR); +		i2c->msg->buf[i2c->msg_ptr++] = byte; + +prepare_read: +		if (is_msglast(i2c)) { +			/* last byte of buffer */ + +			if (is_lastmsg(i2c)) +				writel(I2C_CMD_READ | I2C_CMD_NACK, +							i2c->regs + CMDR); + +		} else if (is_msgend(i2c)) { +			/* ok, we've read the entire buffer, see if there +			 * is anything else we need to do +			*/ + +			if (is_lastmsg(i2c)) { +				/* last message, send stop and complete */ +				dev_dbg(i2c->dev, "READ: Send Stop\n"); + +				nuc900_i2c_stop(i2c, 0); +			} else { +				/* go to the next transfer */ +				dev_dbg(i2c->dev, "READ: Next Transfer\n"); + +				i2c->msg_ptr = 0; +				i2c->msg_idx++; +				i2c->msg++; + +				writel(I2C_CMD_READ, i2c->regs + CMDR); +			} + +		} else { +			writel(I2C_CMD_READ, i2c->regs + CMDR); +		} + +		break; +	} +} + +/* nuc900_i2c_irq + * + * top level IRQ servicing routine +*/ + +static irqreturn_t nuc900_i2c_irq(int irqno, void *dev_id) +{ +	struct nuc900_i2c *i2c = dev_id; +	unsigned long status; + +	status = readl(i2c->regs + CSR); +	writel(status | IRQFLAG, i2c->regs + CSR); + +	if (status & ARBIT_LOST) { +		/* deal with arbitration loss */ +		dev_err(i2c->dev, "deal with arbitration loss\n"); +		goto out; +	} + +	if (i2c->state == STATE_IDLE) { +		dev_dbg(i2c->dev, "IRQ: error i2c->state == IDLE\n"); +		goto out; +	} + +	/* pretty much this leaves us with the fact that we've +	 * transmitted or received whatever byte we last sent +	*/ + +	i2c_nuc900_irq_nextbyte(i2c, status); + + out: +	return IRQ_HANDLED; +} + + +/* nuc900_i2c_set_master + * + * get the i2c bus for a master transaction +*/ + +static int nuc900_i2c_set_master(struct nuc900_i2c *i2c) +{ +	int timeout = 400; + +	while (timeout-- > 0) { +		if (((readl(i2c->regs + SWR) & I2CSTART) == I2CSTART) && +				((readl(i2c->regs + CSR) & I2CBUSY) == 0)) { +			return 0; +		} + +		msleep(1); +	} + +	return -ETIMEDOUT; +} + +/* nuc900_i2c_doxfer + * + * this starts an i2c transfer +*/ + +static int nuc900_i2c_doxfer(struct nuc900_i2c *i2c, +			      struct i2c_msg *msgs, int num) +{ +	unsigned long iicstat, timeout; +	int spins = 20; +	int ret; + +	ret = nuc900_i2c_set_master(i2c); +	if (ret != 0) { +		dev_err(i2c->dev, "cannot get bus (error %d)\n", ret); +		ret = -EAGAIN; +		goto out; +	} + +	spin_lock_irq(&i2c->lock); + +	i2c->msg     = msgs; +	i2c->msg_num = num; +	i2c->msg_ptr = 0; +	i2c->msg_idx = 0; +	i2c->state   = STATE_START; + +	nuc900_i2c_message_start(i2c, msgs); +	spin_unlock_irq(&i2c->lock); + +	timeout = wait_event_timeout(i2c->wait, i2c->msg_num == 0, HZ * 5); + +	ret = i2c->msg_idx; + +	/* having these next two as dev_err() makes life very +	 * noisy when doing an i2cdetect +	*/ + +	if (timeout == 0) +		dev_dbg(i2c->dev, "timeout\n"); +	else if (ret != num) +		dev_dbg(i2c->dev, "incomplete xfer (%d)\n", ret); + +	/* ensure the stop has been through the bus */ + +	dev_dbg(i2c->dev, "waiting for bus idle\n"); + +	/* first, try busy waiting briefly */ +	do { +		iicstat = readl(i2c->regs + CSR); +	} while ((iicstat & I2CBUSY) && --spins); + +	/* if that timed out sleep */ +	if (!spins) { +		msleep(1); +		iicstat = readl(i2c->regs + CSR); +	} + +	if (iicstat & I2CBUSY) +		dev_warn(i2c->dev, "timeout waiting for bus idle\n"); + + out: +	return ret; +} + +/* nuc900_i2c_xfer + * + * first port of call from the i2c bus code when an message needs + * transferring across the i2c bus. +*/ + +static int nuc900_i2c_xfer(struct i2c_adapter *adap, +			struct i2c_msg *msgs, int num) +{ +	struct nuc900_i2c *i2c = (struct nuc900_i2c *)adap->algo_data; +	int retry; +	int ret; + +	nuc900_i2c_enable_irq(i2c); + +	for (retry = 0; retry < adap->retries; retry++) { + +		ret = nuc900_i2c_doxfer(i2c, msgs, num); + +		if (ret != -EAGAIN) +			return ret; + +		dev_dbg(i2c->dev, "Retrying transmission (%d)\n", retry); + +		udelay(100); +	} + +	return -EREMOTEIO; +} + +/* declare our i2c functionality */ +static u32 nuc900_i2c_func(struct i2c_adapter *adap) +{ +	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_PROTOCOL_MANGLING; +} + +/* i2c bus registration info */ + +static const struct i2c_algorithm nuc900_i2c_algorithm = { +	.master_xfer		= nuc900_i2c_xfer, +	.functionality		= nuc900_i2c_func, +}; + +/* nuc900_i2c_probe + * + * called by the bus driver when a suitable device is found +*/ + +static int __devinit nuc900_i2c_probe(struct platform_device *pdev) +{ +	struct nuc900_i2c *i2c; +	struct nuc900_platform_i2c *pdata; +	struct resource *res; +	int ret; + +	pdata = pdev->dev.platform_data; +	if (!pdata) { +		dev_err(&pdev->dev, "no platform data\n"); +		return -EINVAL; +	} + +	i2c = kzalloc(sizeof(struct nuc900_i2c), GFP_KERNEL); +	if (!i2c) { +		dev_err(&pdev->dev, "no memory for state\n"); +		return -ENOMEM; +	} + +	strlcpy(i2c->adap.name, "nuc900-i2c0", sizeof(i2c->adap.name)); +	i2c->adap.owner   = THIS_MODULE; +	i2c->adap.algo    = &nuc900_i2c_algorithm; +	i2c->adap.retries = 2; +	i2c->adap.class   = I2C_CLASS_HWMON | I2C_CLASS_SPD; + +	spin_lock_init(&i2c->lock); +	init_waitqueue_head(&i2c->wait); + +	/* find the clock and enable it */ + +	i2c->dev = &pdev->dev; +	i2c->clk = clk_get(&pdev->dev, NULL); +	if (IS_ERR(i2c->clk)) { +		dev_err(&pdev->dev, "cannot get clock\n"); +		ret = -ENOENT; +		goto err_noclk; +	} + +	dev_dbg(&pdev->dev, "clock source %p\n", i2c->clk); + +	clk_enable(i2c->clk); + +	/* map the registers */ + +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0); +	if (res == NULL) { +		dev_err(&pdev->dev, "cannot find IO resource\n"); +		ret = -ENOENT; +		goto err_clk; +	} + +	i2c->ioarea = request_mem_region(res->start, resource_size(res), +					 pdev->name); + +	if (i2c->ioarea == NULL) { +		dev_err(&pdev->dev, "cannot request IO\n"); +		ret = -ENXIO; +		goto err_clk; +	} + +	i2c->regs = ioremap(res->start, resource_size(res)); + +	if (i2c->regs == NULL) { +		dev_err(&pdev->dev, "cannot map IO\n"); +		ret = -ENXIO; +		goto err_ioarea; +	} + +	dev_dbg(&pdev->dev, "registers %p (%p, %p)\n", +		i2c->regs, i2c->ioarea, res); + +	/* setup info block for the i2c core */ + +	i2c->adap.algo_data = i2c; +	i2c->adap.dev.parent = &pdev->dev; + +	mfp_set_groupg(&pdev->dev); + +	clk_get_rate(i2c->clk); + +	ret = (i2c->clk.apbfreq)/(pdata->bus_freq * 5) - 1; +	writel(ret & 0xffff, i2c->regs + DIVIDER); + +	/* find the IRQ for this unit (note, this relies on the init call to +	 * ensure no current IRQs pending +	 */ + +	i2c->irq = ret = platform_get_irq(pdev, 0); +	if (ret <= 0) { +		dev_err(&pdev->dev, "cannot find IRQ\n"); +		goto err_iomap; +	} + +	ret = request_irq(i2c->irq, nuc900_i2c_irq, IRQF_DISABLED | IRQF_SHARED, +			  dev_name(&pdev->dev), i2c); + +	if (ret != 0) { +		dev_err(&pdev->dev, "cannot claim IRQ %d\n", i2c->irq); +		goto err_iomap; +	} + +	/* Note, previous versions of the driver used i2c_add_adapter() +	 * to add the bus at any number. We now pass the bus number via +	 * the platform data, so if unset it will now default to always +	 * being bus 0. +	 */ + +	i2c->adap.nr = pdata->bus_num; + +	ret = i2c_add_numbered_adapter(&i2c->adap); +	if (ret < 0) { +		dev_err(&pdev->dev, "failed to add bus to i2c core\n"); +		goto err_irq; +	} + +	platform_set_drvdata(pdev, i2c); + +	dev_info(&pdev->dev, "%s: NUC900 I2C adapter\n", +						dev_name(&i2c->adap.dev)); +	return 0; + + err_irq: +	free_irq(i2c->irq, i2c); + + err_iomap: +	iounmap(i2c->regs); + + err_ioarea: +	release_resource(i2c->ioarea); +	kfree(i2c->ioarea); + + err_clk: +	clk_disable(i2c->clk); +	clk_put(i2c->clk); + + err_noclk: +	kfree(i2c); +	return ret; +} + +/* nuc900_i2c_remove + * + * called when device is removed from the bus +*/ + +static int __devexit nuc900_i2c_remove(struct platform_device *pdev) +{ +	struct nuc900_i2c *i2c = platform_get_drvdata(pdev); + +	i2c_del_adapter(&i2c->adap); +	free_irq(i2c->irq, i2c); + +	clk_disable(i2c->clk); +	clk_put(i2c->clk); + +	iounmap(i2c->regs); + +	release_resource(i2c->ioarea); +	kfree(i2c->ioarea); +	kfree(i2c); + +	return 0; +} + +static struct platform_driver nuc900_i2c_driver = { +	.probe		= nuc900_i2c_probe, +	.remove		= __devexit_p(nuc900_i2c_remove), +	.driver		= { +		.owner	= THIS_MODULE, +		.name	= "nuc900-i2c0", +	}, +}; + +static int __init i2c_adap_nuc900_init(void) +{ +	return platform_driver_register(&nuc900_i2c_driver); +} + +static void __exit i2c_adap_nuc900_exit(void) +{ +	platform_driver_unregister(&nuc900_i2c_driver); +} +subsys_initcall(i2c_adap_nuc900_init); +module_exit(i2c_adap_nuc900_exit); + +MODULE_DESCRIPTION("NUC900 I2C Bus driver"); +MODULE_AUTHOR("Wan ZongShun, <mcuos.com-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:nuc900-i2c0"); diff --git a/drivers/i2c/busses/i2c-octeon.c b/drivers/i2c/busses/i2c-octeon.c index 0e9f85d0a83..56dbe54e881 100644 --- a/drivers/i2c/busses/i2c-octeon.c +++ b/drivers/i2c/busses/i2c-octeon.c @@ -218,7 +218,7 @@ static int octeon_i2c_wait(struct octeon_i2c *i2c)  		return result;  	} else if (result == 0) {  		dev_dbg(i2c->dev, "%s: timeout\n", __func__); -		result = -ETIMEDOUT; +		return -ETIMEDOUT;  	}  	return 0; diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index 7674efb5537..b33c78586bf 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c @@ -680,6 +680,8 @@ omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)  	if (r == 0)  		r = num; + +	omap_i2c_wait_for_bb(dev);  out:  	omap_i2c_idle(dev);  	return r; diff --git a/drivers/i2c/busses/i2c-pasemi.c b/drivers/i2c/busses/i2c-pasemi.c index 4174101660c..837b8c1aa02 100644 --- a/drivers/i2c/busses/i2c-pasemi.c +++ b/drivers/i2c/busses/i2c-pasemi.c @@ -88,7 +88,7 @@ static void pasemi_smb_clear(struct pasemi_smbus *smbus)  	reg_write(smbus, REG_SMSTA, status);  } -static unsigned int pasemi_smb_waitready(struct pasemi_smbus *smbus) +static int pasemi_smb_waitready(struct pasemi_smbus *smbus)  {  	int timeout = 10;  	unsigned int status; diff --git a/drivers/i2c/busses/i2c-pca-isa.c b/drivers/i2c/busses/i2c-pca-isa.c index bbd77603a41..29933f87d8f 100644 --- a/drivers/i2c/busses/i2c-pca-isa.c +++ b/drivers/i2c/busses/i2c-pca-isa.c @@ -71,8 +71,8 @@ static int pca_isa_readbyte(void *pd, int reg)  static int pca_isa_waitforcompletion(void *pd)  { -	long ret = ~0;  	unsigned long timeout; +	long ret;  	if (irq > -1) {  		ret = wait_event_timeout(pca_wait, @@ -81,11 +81,15 @@ static int pca_isa_waitforcompletion(void *pd)  	} else {  		/* Do polling */  		timeout = jiffies + pca_isa_ops.timeout; -		while (((pca_isa_readbyte(pd, I2C_PCA_CON) -				& I2C_PCA_CON_SI) == 0) -				&& (ret = time_before(jiffies, timeout))) +		do { +			ret = time_before(jiffies, timeout); +			if (pca_isa_readbyte(pd, I2C_PCA_CON) +					& I2C_PCA_CON_SI) +				break;  			udelay(100); +		} while (ret);  	} +  	return ret > 0;  } diff --git a/drivers/i2c/busses/i2c-pca-platform.c b/drivers/i2c/busses/i2c-pca-platform.c index ef5c78487eb..ace67995d7d 100644 --- a/drivers/i2c/busses/i2c-pca-platform.c +++ b/drivers/i2c/busses/i2c-pca-platform.c @@ -80,8 +80,8 @@ static void i2c_pca_pf_writebyte32(void *pd, int reg, int val)  static int i2c_pca_pf_waitforcompletion(void *pd)  {  	struct i2c_pca_pf_data *i2c = pd; -	long ret = ~0;  	unsigned long timeout; +	long ret;  	if (i2c->irq) {  		ret = wait_event_timeout(i2c->wait, @@ -90,10 +90,13 @@ static int i2c_pca_pf_waitforcompletion(void *pd)  	} else {  		/* Do polling */  		timeout = jiffies + i2c->adap.timeout; -		while (((i2c->algo_data.read_byte(i2c, I2C_PCA_CON) -				& I2C_PCA_CON_SI) == 0) -				&& (ret = time_before(jiffies, timeout))) +		do { +			ret = time_before(jiffies, timeout); +			if (i2c->algo_data.read_byte(i2c, I2C_PCA_CON) +					& I2C_PCA_CON_SI) +				break;  			udelay(100); +		} while (ret);  	}  	return ret > 0; @@ -221,7 +224,7 @@ static int __devinit i2c_pca_pf_probe(struct platform_device *pdev)  	if (irq) {  		ret = request_irq(irq, i2c_pca_pf_handler, -			IRQF_TRIGGER_FALLING, i2c->adap.name, i2c); +			IRQF_TRIGGER_FALLING, pdev->name, i2c);  		if (ret)  			goto e_reqirq;  	} diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c index 020ff23d762..f4c19a97e0b 100644 --- a/drivers/i2c/busses/i2c-pxa.c +++ b/drivers/i2c/busses/i2c-pxa.c @@ -22,7 +22,6 @@  #include <linux/kernel.h>  #include <linux/module.h>  #include <linux/i2c.h> -#include <linux/i2c-id.h>  #include <linux/init.h>  #include <linux/time.h>  #include <linux/sched.h> @@ -1001,7 +1000,7 @@ static int i2c_pxa_probe(struct platform_device *dev)  	struct pxa_i2c *i2c;  	struct resource *res;  	struct i2c_pxa_platform_data *plat = dev->dev.platform_data; -	struct platform_device_id *id = platform_get_device_id(dev); +	const struct platform_device_id *id = platform_get_device_id(dev);  	int ret;  	int irq; diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c index 72902e0bbfa..6a292ea5e35 100644 --- a/drivers/i2c/busses/i2c-s3c2410.c +++ b/drivers/i2c/busses/i2c-s3c2410.c @@ -24,7 +24,6 @@  #include <linux/module.h>  #include <linux/i2c.h> -#include <linux/i2c-id.h>  #include <linux/init.h>  #include <linux/time.h>  #include <linux/interrupt.h> @@ -662,8 +661,8 @@ static int s3c24xx_i2c_clockrate(struct s3c24xx_i2c *i2c, unsigned int *got)  		unsigned long sda_delay;  		if (pdata->sda_delay) { -			sda_delay = (freq / 1000) * pdata->sda_delay; -			sda_delay /= 1000000; +			sda_delay = clkin * pdata->sda_delay; +			sda_delay = DIV_ROUND_UP(sda_delay, 1000000);  			sda_delay = DIV_ROUND_UP(sda_delay, 5);  			if (sda_delay > 3)  				sda_delay = 3; diff --git a/drivers/i2c/busses/i2c-sh7760.c b/drivers/i2c/busses/i2c-sh7760.c index 4f93da31d3a..3cad8fecc3d 100644 --- a/drivers/i2c/busses/i2c-sh7760.c +++ b/drivers/i2c/busses/i2c-sh7760.c @@ -101,12 +101,12 @@ struct cami2c {  static inline void OUT32(struct cami2c *cam, int reg, unsigned long val)  { -	ctrl_outl(val, (unsigned long)cam->iobase + reg); +	__raw_writel(val, (unsigned long)cam->iobase + reg);  }  static inline unsigned long IN32(struct cami2c *cam, int reg)  { -	return ctrl_inl((unsigned long)cam->iobase + reg); +	return __raw_readl((unsigned long)cam->iobase + reg);  }  static irqreturn_t sh7760_i2c_irq(int irq, void *ptr) diff --git a/drivers/i2c/busses/i2c-sh_mobile.c b/drivers/i2c/busses/i2c-sh_mobile.c index ffb405d7c6f..2707f5e1715 100644 --- a/drivers/i2c/busses/i2c-sh_mobile.c +++ b/drivers/i2c/busses/i2c-sh_mobile.c @@ -119,8 +119,10 @@ struct sh_mobile_i2c_data {  	struct i2c_adapter adap;  	struct clk *clk; +	u_int8_t icic;  	u_int8_t iccl;  	u_int8_t icch; +	u_int8_t flags;  	spinlock_t lock;  	wait_queue_head_t wait; @@ -129,15 +131,17 @@ struct sh_mobile_i2c_data {  	int sr;  }; +#define IIC_FLAG_HAS_ICIC67	(1 << 0) +  #define NORMAL_SPEED		100000 /* FAST_SPEED 400000 */  /* Register offsets */ -#define ICDR(pd)		(pd->reg + 0x00) -#define ICCR(pd)		(pd->reg + 0x04) -#define ICSR(pd)		(pd->reg + 0x08) -#define ICIC(pd)		(pd->reg + 0x0c) -#define ICCL(pd)		(pd->reg + 0x10) -#define ICCH(pd)		(pd->reg + 0x14) +#define ICDR			0x00 +#define ICCR			0x04 +#define ICSR			0x08 +#define ICIC			0x0c +#define ICCL			0x10 +#define ICCH			0x14  /* Register bits */  #define ICCR_ICE		0x80 @@ -155,11 +159,32 @@ struct sh_mobile_i2c_data {  #define ICSR_WAIT		0x02  #define ICSR_DTE		0x01 +#define ICIC_ICCLB8		0x80 +#define ICIC_ICCHB8		0x40  #define ICIC_ALE		0x08  #define ICIC_TACKE		0x04  #define ICIC_WAITE		0x02  #define ICIC_DTEE		0x01 +static void iic_wr(struct sh_mobile_i2c_data *pd, int offs, unsigned char data) +{ +	if (offs == ICIC) +		data |= pd->icic; + +	iowrite8(data, pd->reg + offs); +} + +static unsigned char iic_rd(struct sh_mobile_i2c_data *pd, int offs) +{ +	return ioread8(pd->reg + offs); +} + +static void iic_set_clr(struct sh_mobile_i2c_data *pd, int offs, +			unsigned char set, unsigned char clr) +{ +	iic_wr(pd, offs, (iic_rd(pd, offs) | set) & ~clr); +} +  static void activate_ch(struct sh_mobile_i2c_data *pd)  {  	unsigned long i2c_clk; @@ -187,6 +212,14 @@ static void activate_ch(struct sh_mobile_i2c_data *pd)  	else  		pd->iccl = (u_int8_t)(num/denom); +	/* one more bit of ICCL in ICIC */ +	if (pd->flags & IIC_FLAG_HAS_ICIC67) { +		if ((num/denom) > 0xff) +			pd->icic |= ICIC_ICCLB8; +		else +			pd->icic &= ~ICIC_ICCLB8; +	} +  	/* Calculate the value for icch. From the data sheet:  	   icch = (p clock / transfer rate) * (H / (L + H)) */  	num = i2c_clk * 4; @@ -196,25 +229,33 @@ static void activate_ch(struct sh_mobile_i2c_data *pd)  	else  		pd->icch = (u_int8_t)(num/denom); +	/* one more bit of ICCH in ICIC */ +	if (pd->flags & IIC_FLAG_HAS_ICIC67) { +		if ((num/denom) > 0xff) +			pd->icic |= ICIC_ICCHB8; +		else +			pd->icic &= ~ICIC_ICCHB8; +	} +  	/* Enable channel and configure rx ack */ -	iowrite8(ioread8(ICCR(pd)) | ICCR_ICE, ICCR(pd)); +	iic_set_clr(pd, ICCR, ICCR_ICE, 0);  	/* Mask all interrupts */ -	iowrite8(0, ICIC(pd)); +	iic_wr(pd, ICIC, 0);  	/* Set the clock */ -	iowrite8(pd->iccl, ICCL(pd)); -	iowrite8(pd->icch, ICCH(pd)); +	iic_wr(pd, ICCL, pd->iccl); +	iic_wr(pd, ICCH, pd->icch);  }  static void deactivate_ch(struct sh_mobile_i2c_data *pd)  {  	/* Clear/disable interrupts */ -	iowrite8(0, ICSR(pd)); -	iowrite8(0, ICIC(pd)); +	iic_wr(pd, ICSR, 0); +	iic_wr(pd, ICIC, 0);  	/* Disable channel */ -	iowrite8(ioread8(ICCR(pd)) & ~ICCR_ICE, ICCR(pd)); +	iic_set_clr(pd, ICCR, 0, ICCR_ICE);  	/* Disable clock and mark device as idle */  	clk_disable(pd->clk); @@ -233,35 +274,35 @@ static unsigned char i2c_op(struct sh_mobile_i2c_data *pd,  	switch (op) {  	case OP_START: /* issue start and trigger DTE interrupt */ -		iowrite8(0x94, ICCR(pd)); +		iic_wr(pd, ICCR, 0x94);  		break;  	case OP_TX_FIRST: /* disable DTE interrupt and write data */ -		iowrite8(ICIC_WAITE | ICIC_ALE | ICIC_TACKE, ICIC(pd)); -		iowrite8(data, ICDR(pd)); +		iic_wr(pd, ICIC, ICIC_WAITE | ICIC_ALE | ICIC_TACKE); +		iic_wr(pd, ICDR, data);  		break;  	case OP_TX: /* write data */ -		iowrite8(data, ICDR(pd)); +		iic_wr(pd, ICDR, data);  		break;  	case OP_TX_STOP: /* write data and issue a stop afterwards */ -		iowrite8(data, ICDR(pd)); -		iowrite8(0x90, ICCR(pd)); +		iic_wr(pd, ICDR, data); +		iic_wr(pd, ICCR, 0x90);  		break;  	case OP_TX_TO_RX: /* select read mode */ -		iowrite8(0x81, ICCR(pd)); +		iic_wr(pd, ICCR, 0x81);  		break;  	case OP_RX: /* just read data */ -		ret = ioread8(ICDR(pd)); +		ret = iic_rd(pd, ICDR);  		break;  	case OP_RX_STOP: /* enable DTE interrupt, issue stop */ -		iowrite8(ICIC_DTEE | ICIC_WAITE | ICIC_ALE | ICIC_TACKE, -			 ICIC(pd)); -		iowrite8(0xc0, ICCR(pd)); +		iic_wr(pd, ICIC, +		       ICIC_DTEE | ICIC_WAITE | ICIC_ALE | ICIC_TACKE); +		iic_wr(pd, ICCR, 0xc0);  		break;  	case OP_RX_STOP_DATA: /* enable DTE interrupt, read data, issue stop */ -		iowrite8(ICIC_DTEE | ICIC_WAITE | ICIC_ALE | ICIC_TACKE, -			 ICIC(pd)); -		ret = ioread8(ICDR(pd)); -		iowrite8(0xc0, ICCR(pd)); +		iic_wr(pd, ICIC, +		       ICIC_DTEE | ICIC_WAITE | ICIC_ALE | ICIC_TACKE); +		ret = iic_rd(pd, ICDR); +		iic_wr(pd, ICCR, 0xc0);  		break;  	} @@ -367,7 +408,7 @@ static irqreturn_t sh_mobile_i2c_isr(int irq, void *dev_id)  	unsigned char sr;  	int wakeup; -	sr = ioread8(ICSR(pd)); +	sr = iic_rd(pd, ICSR);  	pd->sr |= sr; /* remember state */  	dev_dbg(pd->dev, "i2c_isr 0x%02x 0x%02x %s %d %d!\n", sr, pd->sr, @@ -376,7 +417,7 @@ static irqreturn_t sh_mobile_i2c_isr(int irq, void *dev_id)  	if (sr & (ICSR_AL | ICSR_TACK)) {  		/* don't interrupt transaction - continue to issue stop */ -		iowrite8(sr & ~(ICSR_AL | ICSR_TACK), ICSR(pd)); +		iic_wr(pd, ICSR, sr & ~(ICSR_AL | ICSR_TACK));  		wakeup = 0;  	} else if (pd->msg->flags & I2C_M_RD)  		wakeup = sh_mobile_i2c_isr_rx(pd); @@ -384,7 +425,7 @@ static irqreturn_t sh_mobile_i2c_isr(int irq, void *dev_id)  		wakeup = sh_mobile_i2c_isr_tx(pd);  	if (sr & ICSR_WAIT) /* TODO: add delay here to support slow acks */ -		iowrite8(sr & ~ICSR_WAIT, ICSR(pd)); +		iic_wr(pd, ICSR, sr & ~ICSR_WAIT);  	if (wakeup) {  		pd->sr |= SW_DONE; @@ -402,21 +443,21 @@ static int start_ch(struct sh_mobile_i2c_data *pd, struct i2c_msg *usr_msg)  	}  	/* Initialize channel registers */ -	iowrite8(ioread8(ICCR(pd)) & ~ICCR_ICE, ICCR(pd)); +	iic_set_clr(pd, ICCR, 0, ICCR_ICE);  	/* Enable channel and configure rx ack */ -	iowrite8(ioread8(ICCR(pd)) | ICCR_ICE, ICCR(pd)); +	iic_set_clr(pd, ICCR, ICCR_ICE, 0);  	/* Set the clock */ -	iowrite8(pd->iccl, ICCL(pd)); -	iowrite8(pd->icch, ICCH(pd)); +	iic_wr(pd, ICCL, pd->iccl); +	iic_wr(pd, ICCH, pd->icch);  	pd->msg = usr_msg;  	pd->pos = -1;  	pd->sr = 0;  	/* Enable all interrupts to begin with */ -	iowrite8(ICIC_WAITE | ICIC_ALE | ICIC_TACKE | ICIC_DTEE, ICIC(pd)); +	iic_wr(pd, ICIC, ICIC_DTEE | ICIC_WAITE | ICIC_ALE | ICIC_TACKE);  	return 0;  } @@ -451,7 +492,7 @@ static int sh_mobile_i2c_xfer(struct i2c_adapter *adapter,  		retry_count = 1000;  again: -		val = ioread8(ICSR(pd)); +		val = iic_rd(pd, ICSR);  		dev_dbg(pd->dev, "val 0x%02x pd->sr 0x%02x\n", val, pd->sr); @@ -497,15 +538,17 @@ static int sh_mobile_i2c_hook_irqs(struct platform_device *dev, int hook)  {  	struct resource *res;  	int ret = -ENXIO; -	int q, m; -	int k = 0; -	int n = 0; +	int n, k = 0;  	while ((res = platform_get_resource(dev, IORESOURCE_IRQ, k))) {  		for (n = res->start; hook && n <= res->end; n++) {  			if (request_irq(n, sh_mobile_i2c_isr, IRQF_DISABLED, -					dev_name(&dev->dev), dev)) +					dev_name(&dev->dev), dev)) { +				for (n--; n >= res->start; n--) +					free_irq(n, dev); +  				goto rollback; +			}  		}  		k++;  	} @@ -513,16 +556,17 @@ static int sh_mobile_i2c_hook_irqs(struct platform_device *dev, int hook)  	if (hook)  		return k > 0 ? 0 : -ENOENT; -	k--;  	ret = 0;   rollback: -	for (q = k; k >= 0; k--) { -		for (m = n; m >= res->start; m--) -			free_irq(m, dev); +	k--; + +	while (k >= 0) { +		res = platform_get_resource(dev, IORESOURCE_IRQ, k); +		for (n = res->start; n <= res->end; n++) +			free_irq(n, dev); -		res = platform_get_resource(dev, IORESOURCE_IRQ, k - 1); -		m = res->end; +		k--;  	}  	return ret; @@ -576,6 +620,12 @@ static int sh_mobile_i2c_probe(struct platform_device *dev)  		goto err_irq;  	} +	/* The IIC blocks on SH-Mobile ARM processors +	 * come with two new bits in ICIC. +	 */ +	if (size > 0x17) +		pd->flags |= IIC_FLAG_HAS_ICIC67; +  	/* Enable Runtime PM for this device.  	 *  	 * Also tell the Runtime PM core to ignore children diff --git a/drivers/i2c/busses/i2c-viapro.c b/drivers/i2c/busses/i2c-viapro.c index 4c6fff5f330..0b012f1f8ac 100644 --- a/drivers/i2c/busses/i2c-viapro.c +++ b/drivers/i2c/busses/i2c-viapro.c @@ -185,14 +185,8 @@ static int vt596_transaction(u8 size)  	}  	if (temp & 0x04) { -		int read = inb_p(SMBHSTADD) & 0x01;  		result = -ENXIO; -		/* The quick and receive byte commands are used to probe -		   for chips, so errors are expected, and we don't want -		   to frighten the user. */ -		if (!((size == VT596_QUICK && !read) || -		      (size == VT596_BYTE && read))) -			dev_err(&vt596_adapter.dev, "Transaction error!\n"); +		dev_dbg(&vt596_adapter.dev, "No response\n");  	}  	/* Resetting status register */ diff --git a/drivers/i2c/busses/scx200_acb.c b/drivers/i2c/busses/scx200_acb.c index 4cb4bb00995..53fab518b3d 100644 --- a/drivers/i2c/busses/scx200_acb.c +++ b/drivers/i2c/busses/scx200_acb.c @@ -560,7 +560,8 @@ static const struct pci_device_id scx200_pci[] __initconst = {  	{ PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_CS5535_ISA),  	  .driver_data = 1 },  	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_ISA), -	  .driver_data = 2 } +	  .driver_data = 2 }, +	{ 0, }  };  static struct { diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index 0815e10da7c..d231f683f57 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -20,7 +20,9 @@  /* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi>.     All SMBus-related things are written by Frodo Looijaard <frodol@dds.nl>     SMBus 2.0 support by Mark Studebaker <mdsxyz123@yahoo.com> and -   Jean Delvare <khali@linux-fr.org> */ +   Jean Delvare <khali@linux-fr.org> +   Mux support by Rodolfo Giometti <giometti@enneenne.com> and +   Michael Lawnick <michael.lawnick.ext@nsn.com> */  #include <linux/module.h>  #include <linux/kernel.h> @@ -30,6 +32,7 @@  #include <linux/init.h>  #include <linux/idr.h>  #include <linux/mutex.h> +#include <linux/of_device.h>  #include <linux/completion.h>  #include <linux/hardirq.h>  #include <linux/irqflags.h> @@ -70,6 +73,10 @@ static int i2c_device_match(struct device *dev, struct device_driver *drv)  	if (!client)  		return 0; +	/* Attempt an OF style match */ +	if (of_driver_match_device(dev, drv)) +		return 1; +  	driver = to_i2c_driver(drv);  	/* match on an id table if there is one */  	if (driver->id_table) @@ -189,11 +196,12 @@ static int i2c_device_pm_suspend(struct device *dev)  {  	const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; -	if (pm_runtime_suspended(dev)) -		return 0; - -	if (pm) -		return pm->suspend ? pm->suspend(dev) : 0; +	if (pm) { +		if (pm_runtime_suspended(dev)) +			return 0; +		else +			return pm->suspend ? pm->suspend(dev) : 0; +	}  	return i2c_legacy_suspend(dev, PMSG_SUSPEND);  } @@ -208,12 +216,6 @@ static int i2c_device_pm_resume(struct device *dev)  	else  		ret = i2c_legacy_resume(dev); -	if (!ret) { -		pm_runtime_disable(dev); -		pm_runtime_set_active(dev); -		pm_runtime_enable(dev); -	} -  	return ret;  } @@ -221,11 +223,12 @@ static int i2c_device_pm_freeze(struct device *dev)  {  	const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; -	if (pm_runtime_suspended(dev)) -		return 0; - -	if (pm) -		return pm->freeze ? pm->freeze(dev) : 0; +	if (pm) { +		if (pm_runtime_suspended(dev)) +			return 0; +		else +			return pm->freeze ? pm->freeze(dev) : 0; +	}  	return i2c_legacy_suspend(dev, PMSG_FREEZE);  } @@ -234,11 +237,12 @@ static int i2c_device_pm_thaw(struct device *dev)  {  	const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; -	if (pm_runtime_suspended(dev)) -		return 0; - -	if (pm) -		return pm->thaw ? pm->thaw(dev) : 0; +	if (pm) { +		if (pm_runtime_suspended(dev)) +			return 0; +		else +			return pm->thaw ? pm->thaw(dev) : 0; +	}  	return i2c_legacy_resume(dev);  } @@ -247,11 +251,12 @@ static int i2c_device_pm_poweroff(struct device *dev)  {  	const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; -	if (pm_runtime_suspended(dev)) -		return 0; - -	if (pm) -		return pm->poweroff ? pm->poweroff(dev) : 0; +	if (pm) { +		if (pm_runtime_suspended(dev)) +			return 0; +		else +			return pm->poweroff ? pm->poweroff(dev) : 0; +	}  	return i2c_legacy_suspend(dev, PMSG_HIBERNATE);  } @@ -417,13 +422,95 @@ static int __i2c_check_addr_busy(struct device *dev, void *addrp)  	return 0;  } +/* walk up mux tree */ +static int i2c_check_mux_parents(struct i2c_adapter *adapter, int addr) +{ +	struct i2c_adapter *parent = i2c_parent_is_i2c_adapter(adapter); +	int result; + +	result = device_for_each_child(&adapter->dev, &addr, +					__i2c_check_addr_busy); + +	if (!result && parent) +		result = i2c_check_mux_parents(parent, addr); + +	return result; +} + +/* recurse down mux tree */ +static int i2c_check_mux_children(struct device *dev, void *addrp) +{ +	int result; + +	if (dev->type == &i2c_adapter_type) +		result = device_for_each_child(dev, addrp, +						i2c_check_mux_children); +	else +		result = __i2c_check_addr_busy(dev, addrp); + +	return result; +} +  static int i2c_check_addr_busy(struct i2c_adapter *adapter, int addr)  { -	return device_for_each_child(&adapter->dev, &addr, -				     __i2c_check_addr_busy); +	struct i2c_adapter *parent = i2c_parent_is_i2c_adapter(adapter); +	int result = 0; + +	if (parent) +		result = i2c_check_mux_parents(parent, addr); + +	if (!result) +		result = device_for_each_child(&adapter->dev, &addr, +						i2c_check_mux_children); + +	return result; +} + +/** + * i2c_lock_adapter - Get exclusive access to an I2C bus segment + * @adapter: Target I2C bus segment + */ +void i2c_lock_adapter(struct i2c_adapter *adapter) +{ +	struct i2c_adapter *parent = i2c_parent_is_i2c_adapter(adapter); + +	if (parent) +		i2c_lock_adapter(parent); +	else +		rt_mutex_lock(&adapter->bus_lock); +} +EXPORT_SYMBOL_GPL(i2c_lock_adapter); + +/** + * i2c_trylock_adapter - Try to get exclusive access to an I2C bus segment + * @adapter: Target I2C bus segment + */ +static int i2c_trylock_adapter(struct i2c_adapter *adapter) +{ +	struct i2c_adapter *parent = i2c_parent_is_i2c_adapter(adapter); + +	if (parent) +		return i2c_trylock_adapter(parent); +	else +		return rt_mutex_trylock(&adapter->bus_lock);  }  /** + * i2c_unlock_adapter - Release exclusive access to an I2C bus segment + * @adapter: Target I2C bus segment + */ +void i2c_unlock_adapter(struct i2c_adapter *adapter) +{ +	struct i2c_adapter *parent = i2c_parent_is_i2c_adapter(adapter); + +	if (parent) +		i2c_unlock_adapter(parent); +	else +		rt_mutex_unlock(&adapter->bus_lock); +} +EXPORT_SYMBOL_GPL(i2c_unlock_adapter); + +/**   * i2c_new_device - instantiate an i2c device   * @adap: the adapter managing the device   * @info: describes one I2C device; bus_num is ignored @@ -596,8 +683,6 @@ i2c_sysfs_new_device(struct device *dev, struct device_attribute *attr,  	char *blank, end;  	int res; -	dev_warn(dev, "The new_device interface is still experimental " -		 "and may change in a near future\n");  	memset(&info, 0, sizeof(struct i2c_board_info));  	blank = strchr(buf, ' '); @@ -627,9 +712,9 @@ i2c_sysfs_new_device(struct device *dev, struct device_attribute *attr,  		return -EINVAL;  	/* Keep track of the added device */ -	i2c_lock_adapter(adap); +	mutex_lock(&adap->userspace_clients_lock);  	list_add_tail(&client->detected, &adap->userspace_clients); -	i2c_unlock_adapter(adap); +	mutex_unlock(&adap->userspace_clients_lock);  	dev_info(dev, "%s: Instantiated device %s at 0x%02hx\n", "new_device",  		 info.type, info.addr); @@ -668,7 +753,7 @@ i2c_sysfs_delete_device(struct device *dev, struct device_attribute *attr,  	/* Make sure the device was added through sysfs */  	res = -ENOENT; -	i2c_lock_adapter(adap); +	mutex_lock(&adap->userspace_clients_lock);  	list_for_each_entry_safe(client, next, &adap->userspace_clients,  				 detected) {  		if (client->addr == addr) { @@ -681,7 +766,7 @@ i2c_sysfs_delete_device(struct device *dev, struct device_attribute *attr,  			break;  		}  	} -	i2c_unlock_adapter(adap); +	mutex_unlock(&adap->userspace_clients_lock);  	if (res < 0)  		dev_err(dev, "%s: Can't find device in list\n", @@ -708,10 +793,11 @@ static const struct attribute_group *i2c_adapter_attr_groups[] = {  	NULL  }; -static struct device_type i2c_adapter_type = { +struct device_type i2c_adapter_type = {  	.groups		= i2c_adapter_attr_groups,  	.release	= i2c_adapter_dev_release,  }; +EXPORT_SYMBOL_GPL(i2c_adapter_type);  #ifdef CONFIG_I2C_COMPAT  static struct class_compat *i2c_adapter_compat_class; @@ -754,7 +840,7 @@ static int __process_new_adapter(struct device_driver *d, void *data)  static int i2c_register_adapter(struct i2c_adapter *adap)  { -	int res = 0, dummy; +	int res = 0;  	/* Can't register until after driver model init */  	if (unlikely(WARN_ON(!i2c_bus_type.p))) { @@ -763,6 +849,7 @@ static int i2c_register_adapter(struct i2c_adapter *adap)  	}  	rt_mutex_init(&adap->bus_lock); +	mutex_init(&adap->userspace_clients_lock);  	INIT_LIST_HEAD(&adap->userspace_clients);  	/* Set default timeout to 1 second if not already set */ @@ -792,8 +879,7 @@ static int i2c_register_adapter(struct i2c_adapter *adap)  	/* Notify drivers */  	mutex_lock(&core_lock); -	dummy = bus_for_each_drv(&i2c_bus_type, NULL, adap, -				 __process_new_adapter); +	bus_for_each_drv(&i2c_bus_type, NULL, adap, __process_new_adapter);  	mutex_unlock(&core_lock);  	return 0; @@ -966,7 +1052,7 @@ int i2c_del_adapter(struct i2c_adapter *adap)  		return res;  	/* Remove devices instantiated from sysfs */ -	i2c_lock_adapter(adap); +	mutex_lock(&adap->userspace_clients_lock);  	list_for_each_entry_safe(client, next, &adap->userspace_clients,  				 detected) {  		dev_dbg(&adap->dev, "Removing %s at 0x%x\n", client->name, @@ -974,7 +1060,7 @@ int i2c_del_adapter(struct i2c_adapter *adap)  		list_del(&client->detected);  		i2c_unregister_device(client);  	} -	i2c_unlock_adapter(adap); +	mutex_unlock(&adap->userspace_clients_lock);  	/* Detach any active clients. This can't fail, thus we do not  	   checking the returned value. */ @@ -1229,12 +1315,12 @@ int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)  #endif  		if (in_atomic() || irqs_disabled()) { -			ret = rt_mutex_trylock(&adap->bus_lock); +			ret = i2c_trylock_adapter(adap);  			if (!ret)  				/* I2C activity is ongoing. */  				return -EAGAIN;  		} else { -			rt_mutex_lock(&adap->bus_lock); +			i2c_lock_adapter(adap);  		}  		/* Retry automatically on arbitration loss */ @@ -1246,7 +1332,7 @@ int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)  			if (time_after(jiffies, orig_jiffies + adap->timeout))  				break;  		} -		rt_mutex_unlock(&adap->bus_lock); +		i2c_unlock_adapter(adap);  		return ret;  	} else { @@ -1341,13 +1427,17 @@ static int i2c_default_probe(struct i2c_adapter *adap, unsigned short addr)  				     I2C_SMBUS_BYTE_DATA, &dummy);  	else  #endif -	if ((addr & ~0x07) == 0x30 || (addr & ~0x0f) == 0x50 -	 || !i2c_check_functionality(adap, I2C_FUNC_SMBUS_QUICK)) -		err = i2c_smbus_xfer(adap, addr, 0, I2C_SMBUS_READ, 0, -				     I2C_SMBUS_BYTE, &dummy); -	else +	if (!((addr & ~0x07) == 0x30 || (addr & ~0x0f) == 0x50) +	 && i2c_check_functionality(adap, I2C_FUNC_SMBUS_QUICK))  		err = i2c_smbus_xfer(adap, addr, 0, I2C_SMBUS_WRITE, 0,  				     I2C_SMBUS_QUICK, NULL); +	else if (i2c_check_functionality(adap, I2C_FUNC_SMBUS_READ_BYTE)) +		err = i2c_smbus_xfer(adap, addr, 0, I2C_SMBUS_READ, 0, +				     I2C_SMBUS_BYTE, &dummy); +	else { +		dev_warn(&adap->dev, "No suitable probing method supported\n"); +		err = -EOPNOTSUPP; +	}  	return err >= 0;  } @@ -1418,52 +1508,46 @@ static int i2c_detect(struct i2c_adapter *adapter, struct i2c_driver *driver)  	if (!driver->detect || !address_list)  		return 0; +	/* Stop here if the classes do not match */ +	if (!(adapter->class & driver->class)) +		return 0; +  	/* Set up a temporary client to help detect callback */  	temp_client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);  	if (!temp_client)  		return -ENOMEM;  	temp_client->adapter = adapter; -	/* Stop here if the classes do not match */ -	if (!(adapter->class & driver->class)) -		goto exit_free; - -	/* Stop here if the bus doesn't support probing */ -	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_BYTE)) { -		if (address_list[0] == I2C_CLIENT_END) -			goto exit_free; - -		dev_warn(&adapter->dev, "Probing not supported\n"); -		err = -EOPNOTSUPP; -		goto exit_free; -	} -  	for (i = 0; address_list[i] != I2C_CLIENT_END; i += 1) {  		dev_dbg(&adapter->dev, "found normal entry for adapter %d, "  			"addr 0x%02x\n", adap_id, address_list[i]);  		temp_client->addr = address_list[i];  		err = i2c_detect_address(temp_client, driver); -		if (err) -			goto exit_free; +		if (unlikely(err)) +			break;  	} - exit_free:  	kfree(temp_client);  	return err;  } +int i2c_probe_func_quick_read(struct i2c_adapter *adap, unsigned short addr) +{ +	return i2c_smbus_xfer(adap, addr, 0, I2C_SMBUS_READ, 0, +			      I2C_SMBUS_QUICK, NULL) >= 0; +} +EXPORT_SYMBOL_GPL(i2c_probe_func_quick_read); +  struct i2c_client *  i2c_new_probed_device(struct i2c_adapter *adap,  		      struct i2c_board_info *info, -		      unsigned short const *addr_list) +		      unsigned short const *addr_list, +		      int (*probe)(struct i2c_adapter *, unsigned short addr))  {  	int i; -	/* Stop here if the bus doesn't support probing */ -	if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_READ_BYTE)) { -		dev_err(&adap->dev, "Probing not supported\n"); -		return NULL; -	} +	if (!probe) +		probe = i2c_default_probe;  	for (i = 0; addr_list[i] != I2C_CLIENT_END; i++) {  		/* Check address validity */ @@ -1481,7 +1565,7 @@ i2c_new_probed_device(struct i2c_adapter *adap,  		}  		/* Test address responsiveness */ -		if (i2c_default_probe(adap, addr_list[i])) +		if (probe(adap, addr_list[i]))  			break;  	} @@ -1993,7 +2077,7 @@ s32 i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr, unsigned short flags,  	flags &= I2C_M_TEN | I2C_CLIENT_PEC;  	if (adapter->algo->smbus_xfer) { -		rt_mutex_lock(&adapter->bus_lock); +		i2c_lock_adapter(adapter);  		/* Retry automatically on arbitration loss */  		orig_jiffies = jiffies; @@ -2007,7 +2091,7 @@ s32 i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr, unsigned short flags,  				       orig_jiffies + adapter->timeout))  				break;  		} -		rt_mutex_unlock(&adapter->bus_lock); +		i2c_unlock_adapter(adapter);  	} else  		res = i2c_smbus_xfer_emulated(adapter, addr, flags, read_write,  					      command, protocol, data); diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c index e0694e4d86c..cec0f3ba97f 100644 --- a/drivers/i2c/i2c-dev.c +++ b/drivers/i2c/i2c-dev.c @@ -167,13 +167,9 @@ static ssize_t i2cdev_write(struct file *file, const char __user *buf,  	if (count > 8192)  		count = 8192; -	tmp = kmalloc(count, GFP_KERNEL); -	if (tmp == NULL) -		return -ENOMEM; -	if (copy_from_user(tmp, buf, count)) { -		kfree(tmp); -		return -EFAULT; -	} +	tmp = memdup_user(buf, count); +	if (IS_ERR(tmp)) +		return PTR_ERR(tmp);  	pr_debug("i2c-dev: i2c-%d writing %zu bytes.\n",  		iminor(file->f_path.dentry->d_inode), count); @@ -193,12 +189,49 @@ static int i2cdev_check(struct device *dev, void *addrp)  	return dev->driver ? -EBUSY : 0;  } +/* walk up mux tree */ +static int i2cdev_check_mux_parents(struct i2c_adapter *adapter, int addr) +{ +	struct i2c_adapter *parent = i2c_parent_is_i2c_adapter(adapter); +	int result; + +	result = device_for_each_child(&adapter->dev, &addr, i2cdev_check); +	if (!result && parent) +		result = i2cdev_check_mux_parents(parent, addr); + +	return result; +} + +/* recurse down mux tree */ +static int i2cdev_check_mux_children(struct device *dev, void *addrp) +{ +	int result; + +	if (dev->type == &i2c_adapter_type) +		result = device_for_each_child(dev, addrp, +						i2cdev_check_mux_children); +	else +		result = i2cdev_check(dev, addrp); + +	return result; +} +  /* This address checking function differs from the one in i2c-core     in that it considers an address with a registered device, but no     driver bound to it, as NOT busy. */  static int i2cdev_check_addr(struct i2c_adapter *adapter, unsigned int addr)  { -	return device_for_each_child(&adapter->dev, &addr, i2cdev_check); +	struct i2c_adapter *parent = i2c_parent_is_i2c_adapter(adapter); +	int result = 0; + +	if (parent) +		result = i2cdev_check_mux_parents(parent, addr); + +	if (!result) +		result = device_for_each_child(&adapter->dev, &addr, +						i2cdev_check_mux_children); + +	return result;  }  static noinline int i2cdev_ioctl_rdrw(struct i2c_client *client, @@ -219,9 +252,7 @@ static noinline int i2cdev_ioctl_rdrw(struct i2c_client *client,  	if (rdwr_arg.nmsgs > I2C_RDRW_IOCTL_MAX_MSGS)  		return -EINVAL; -	rdwr_pa = (struct i2c_msg *) -		kmalloc(rdwr_arg.nmsgs * sizeof(struct i2c_msg), -		GFP_KERNEL); +	rdwr_pa = kmalloc(rdwr_arg.nmsgs * sizeof(struct i2c_msg), GFP_KERNEL);  	if (!rdwr_pa)  		return -ENOMEM; @@ -247,15 +278,9 @@ static noinline int i2cdev_ioctl_rdrw(struct i2c_client *client,  			break;  		}  		data_ptrs[i] = (u8 __user *)rdwr_pa[i].buf; -		rdwr_pa[i].buf = kmalloc(rdwr_pa[i].len, GFP_KERNEL); -		if (rdwr_pa[i].buf == NULL) { -			res = -ENOMEM; -			break; -		} -		if (copy_from_user(rdwr_pa[i].buf, data_ptrs[i], -				   rdwr_pa[i].len)) { -				++i; /* Needs to be kfreed too */ -				res = -EFAULT; +		rdwr_pa[i].buf = memdup_user(data_ptrs[i], rdwr_pa[i].len); +		if (IS_ERR(rdwr_pa[i].buf)) { +			res = PTR_ERR(rdwr_pa[i].buf);  			break;  		}  	} diff --git a/drivers/i2c/i2c-mux.c b/drivers/i2c/i2c-mux.c new file mode 100644 index 00000000000..d32a4843fc3 --- /dev/null +++ b/drivers/i2c/i2c-mux.c @@ -0,0 +1,165 @@ +/* + * Multiplexed I2C bus driver. + * + * Copyright (c) 2008-2009 Rodolfo Giometti <giometti@linux.it> + * Copyright (c) 2008-2009 Eurotech S.p.A. <info@eurotech.it> + * Copyright (c) 2009-2010 NSN GmbH & Co KG <michael.lawnick.ext@nsn.com> + * + * Simplifies access to complex multiplexed I2C bus topologies, by presenting + * each multiplexed bus segment as an additional I2C adapter. + * Supports multi-level mux'ing (mux behind a mux). + * + * Based on: + *	i2c-virt.c from Kumar Gala <galak@kernel.crashing.org> + *	i2c-virtual.c from Ken Harrenstien, Copyright (c) 2004 Google, Inc. + *	i2c-virtual.c from Brian Kuschak <bkuschak@yahoo.com> + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/slab.h> +#include <linux/i2c.h> +#include <linux/i2c-mux.h> + +/* multiplexer per channel data */ +struct i2c_mux_priv { +	struct i2c_adapter adap; +	struct i2c_algorithm algo; + +	struct i2c_adapter *parent; +	void *mux_dev;	/* the mux chip/device */ +	u32  chan_id;	/* the channel id */ + +	int (*select)(struct i2c_adapter *, void *mux_dev, u32 chan_id); +	int (*deselect)(struct i2c_adapter *, void *mux_dev, u32 chan_id); +}; + +static int i2c_mux_master_xfer(struct i2c_adapter *adap, +			       struct i2c_msg msgs[], int num) +{ +	struct i2c_mux_priv *priv = adap->algo_data; +	struct i2c_adapter *parent = priv->parent; +	int ret; + +	/* Switch to the right mux port and perform the transfer. */ + +	ret = priv->select(parent, priv->mux_dev, priv->chan_id); +	if (ret >= 0) +		ret = parent->algo->master_xfer(parent, msgs, num); +	if (priv->deselect) +		priv->deselect(parent, priv->mux_dev, priv->chan_id); + +	return ret; +} + +static int i2c_mux_smbus_xfer(struct i2c_adapter *adap, +			      u16 addr, unsigned short flags, +			      char read_write, u8 command, +			      int size, union i2c_smbus_data *data) +{ +	struct i2c_mux_priv *priv = adap->algo_data; +	struct i2c_adapter *parent = priv->parent; +	int ret; + +	/* Select the right mux port and perform the transfer. */ + +	ret = priv->select(parent, priv->mux_dev, priv->chan_id); +	if (ret >= 0) +		ret = parent->algo->smbus_xfer(parent, addr, flags, +					read_write, command, size, data); +	if (priv->deselect) +		priv->deselect(parent, priv->mux_dev, priv->chan_id); + +	return ret; +} + +/* Return the parent's functionality */ +static u32 i2c_mux_functionality(struct i2c_adapter *adap) +{ +	struct i2c_mux_priv *priv = adap->algo_data; +	struct i2c_adapter *parent = priv->parent; + +	return parent->algo->functionality(parent); +} + +struct i2c_adapter *i2c_add_mux_adapter(struct i2c_adapter *parent, +				void *mux_dev, u32 force_nr, u32 chan_id, +				int (*select) (struct i2c_adapter *, +					       void *, u32), +				int (*deselect) (struct i2c_adapter *, +						 void *, u32)) +{ +	struct i2c_mux_priv *priv; +	int ret; + +	priv = kzalloc(sizeof(struct i2c_mux_priv), GFP_KERNEL); +	if (!priv) +		return NULL; + +	/* Set up private adapter data */ +	priv->parent = parent; +	priv->mux_dev = mux_dev; +	priv->chan_id = chan_id; +	priv->select = select; +	priv->deselect = deselect; + +	/* Need to do algo dynamically because we don't know ahead +	 * of time what sort of physical adapter we'll be dealing with. +	 */ +	if (parent->algo->master_xfer) +		priv->algo.master_xfer = i2c_mux_master_xfer; +	if (parent->algo->smbus_xfer) +		priv->algo.smbus_xfer = i2c_mux_smbus_xfer; +	priv->algo.functionality = i2c_mux_functionality; + +	/* Now fill out new adapter structure */ +	snprintf(priv->adap.name, sizeof(priv->adap.name), +		 "i2c-%d-mux (chan_id %d)", i2c_adapter_id(parent), chan_id); +	priv->adap.owner = THIS_MODULE; +	priv->adap.id = parent->id; +	priv->adap.algo = &priv->algo; +	priv->adap.algo_data = priv; +	priv->adap.dev.parent = &parent->dev; + +	if (force_nr) { +		priv->adap.nr = force_nr; +		ret = i2c_add_numbered_adapter(&priv->adap); +	} else { +		ret = i2c_add_adapter(&priv->adap); +	} +	if (ret < 0) { +		dev_err(&parent->dev, +			"failed to add mux-adapter (error=%d)\n", +			ret); +		kfree(priv); +		return NULL; +	} + +	dev_info(&parent->dev, "Added multiplexed i2c bus %d\n", +		 i2c_adapter_id(&priv->adap)); + +	return &priv->adap; +} +EXPORT_SYMBOL_GPL(i2c_add_mux_adapter); + +int i2c_del_mux_adapter(struct i2c_adapter *adap) +{ +	struct i2c_mux_priv *priv = adap->algo_data; +	int ret; + +	ret = i2c_del_adapter(adap); +	if (ret < 0) +		return ret; +	kfree(priv); + +	return 0; +} +EXPORT_SYMBOL_GPL(i2c_del_mux_adapter); + +MODULE_AUTHOR("Rodolfo Giometti <giometti@linux.it>"); +MODULE_DESCRIPTION("I2C driver for multiplexed I2C busses"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/i2c/muxes/Kconfig b/drivers/i2c/muxes/Kconfig new file mode 100644 index 00000000000..4d91d80bfd2 --- /dev/null +++ b/drivers/i2c/muxes/Kconfig @@ -0,0 +1,28 @@ +# +# Multiplexer I2C chip drivers configuration +# + +menu "Multiplexer I2C Chip support" +	depends on I2C_MUX + +config I2C_MUX_PCA9541 +	tristate "NXP PCA9541 I2C Master Selector" +	depends on EXPERIMENTAL +	help +	  If you say yes here you get support for the NXP PCA9541 +	  I2C Master Selector. + +	  This driver can also be built as a module.  If so, the module +	  will be called pca9541. + +config I2C_MUX_PCA954x +	tristate "Philips PCA954x I2C Mux/switches" +	depends on EXPERIMENTAL +	help +	  If you say yes here you get support for the Philips PCA954x +	  I2C mux/switch devices. + +	  This driver can also be built as a module.  If so, the module +	  will be called pca954x. + +endmenu diff --git a/drivers/i2c/muxes/Makefile b/drivers/i2c/muxes/Makefile new file mode 100644 index 00000000000..d743806d9b4 --- /dev/null +++ b/drivers/i2c/muxes/Makefile @@ -0,0 +1,7 @@ +# +# Makefile for multiplexer I2C chip drivers. + +obj-$(CONFIG_I2C_MUX_PCA9541)	+= pca9541.o +obj-$(CONFIG_I2C_MUX_PCA954x)	+= pca954x.o + +ccflags-$(CONFIG_I2C_DEBUG_BUS) := -DDEBUG diff --git a/drivers/i2c/muxes/pca9541.c b/drivers/i2c/muxes/pca9541.c new file mode 100644 index 00000000000..ed699c5aa79 --- /dev/null +++ b/drivers/i2c/muxes/pca9541.c @@ -0,0 +1,411 @@ +/* + * I2C multiplexer driver for PCA9541 bus master selector + * + * Copyright (c) 2010 Ericsson AB. + * + * Author: Guenter Roeck <guenter.roeck@ericsson.com> + * + * Derived from: + *  pca954x.c + * + *  Copyright (c) 2008-2009 Rodolfo Giometti <giometti@linux.it> + *  Copyright (c) 2008-2009 Eurotech S.p.A. <info@eurotech.it> + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include <linux/module.h> +#include <linux/init.h> +#include <linux/jiffies.h> +#include <linux/delay.h> +#include <linux/slab.h> +#include <linux/device.h> +#include <linux/i2c.h> +#include <linux/i2c-mux.h> + +#include <linux/i2c/pca954x.h> + +/* + * The PCA9541 is a bus master selector. It supports two I2C masters connected + * to a single slave bus. + * + * Before each bus transaction, a master has to acquire bus ownership. After the + * transaction is complete, bus ownership has to be released. This fits well + * into the I2C multiplexer framework, which provides select and release + * functions for this purpose. For this reason, this driver is modeled as + * single-channel I2C bus multiplexer. + * + * This driver assumes that the two bus masters are controlled by two different + * hosts. If a single host controls both masters, platform code has to ensure + * that only one of the masters is instantiated at any given time. + */ + +#define PCA9541_CONTROL		0x01 +#define PCA9541_ISTAT		0x02 + +#define PCA9541_CTL_MYBUS	(1 << 0) +#define PCA9541_CTL_NMYBUS	(1 << 1) +#define PCA9541_CTL_BUSON	(1 << 2) +#define PCA9541_CTL_NBUSON	(1 << 3) +#define PCA9541_CTL_BUSINIT	(1 << 4) +#define PCA9541_CTL_TESTON	(1 << 6) +#define PCA9541_CTL_NTESTON	(1 << 7) + +#define PCA9541_ISTAT_INTIN	(1 << 0) +#define PCA9541_ISTAT_BUSINIT	(1 << 1) +#define PCA9541_ISTAT_BUSOK	(1 << 2) +#define PCA9541_ISTAT_BUSLOST	(1 << 3) +#define PCA9541_ISTAT_MYTEST	(1 << 6) +#define PCA9541_ISTAT_NMYTEST	(1 << 7) + +#define BUSON		(PCA9541_CTL_BUSON | PCA9541_CTL_NBUSON) +#define MYBUS		(PCA9541_CTL_MYBUS | PCA9541_CTL_NMYBUS) +#define mybus(x)	(!((x) & MYBUS) || ((x) & MYBUS) == MYBUS) +#define busoff(x)	(!((x) & BUSON) || ((x) & BUSON) == BUSON) + +/* arbitration timeouts, in jiffies */ +#define ARB_TIMEOUT	(HZ / 8)	/* 125 ms until forcing bus ownership */ +#define ARB2_TIMEOUT	(HZ / 4)	/* 250 ms until acquisition failure */ + +/* arbitration retry delays, in us */ +#define SELECT_DELAY_SHORT	50 +#define SELECT_DELAY_LONG	1000 + +struct pca9541 { +	struct i2c_adapter *mux_adap; +	unsigned long select_timeout; +	unsigned long arb_timeout; +}; + +static const struct i2c_device_id pca9541_id[] = { +	{"pca9541", 0}, +	{} +}; + +MODULE_DEVICE_TABLE(i2c, pca9541_id); + +/* + * Write to chip register. Don't use i2c_transfer()/i2c_smbus_xfer() + * as they will try to lock the adapter a second time. + */ +static int pca9541_reg_write(struct i2c_client *client, u8 command, u8 val) +{ +	struct i2c_adapter *adap = client->adapter; +	int ret; + +	if (adap->algo->master_xfer) { +		struct i2c_msg msg; +		char buf[2]; + +		msg.addr = client->addr; +		msg.flags = 0; +		msg.len = 2; +		buf[0] = command; +		buf[1] = val; +		msg.buf = buf; +		ret = adap->algo->master_xfer(adap, &msg, 1); +	} else { +		union i2c_smbus_data data; + +		data.byte = val; +		ret = adap->algo->smbus_xfer(adap, client->addr, +					     client->flags, +					     I2C_SMBUS_WRITE, +					     command, +					     I2C_SMBUS_BYTE_DATA, &data); +	} + +	return ret; +} + +/* + * Read from chip register. Don't use i2c_transfer()/i2c_smbus_xfer() + * as they will try to lock adapter a second time. + */ +static int pca9541_reg_read(struct i2c_client *client, u8 command) +{ +	struct i2c_adapter *adap = client->adapter; +	int ret; +	u8 val; + +	if (adap->algo->master_xfer) { +		struct i2c_msg msg[2] = { +			{ +				.addr = client->addr, +				.flags = 0, +				.len = 1, +				.buf = &command +			}, +			{ +				.addr = client->addr, +				.flags = I2C_M_RD, +				.len = 1, +				.buf = &val +			} +		}; +		ret = adap->algo->master_xfer(adap, msg, 2); +		if (ret == 2) +			ret = val; +		else if (ret >= 0) +			ret = -EIO; +	} else { +		union i2c_smbus_data data; + +		ret = adap->algo->smbus_xfer(adap, client->addr, +					     client->flags, +					     I2C_SMBUS_READ, +					     command, +					     I2C_SMBUS_BYTE_DATA, &data); +		if (!ret) +			ret = data.byte; +	} +	return ret; +} + +/* + * Arbitration management functions + */ + +/* Release bus. Also reset NTESTON and BUSINIT if it was set. */ +static void pca9541_release_bus(struct i2c_client *client) +{ +	int reg; + +	reg = pca9541_reg_read(client, PCA9541_CONTROL); +	if (reg >= 0 && !busoff(reg) && mybus(reg)) +		pca9541_reg_write(client, PCA9541_CONTROL, +				  (reg & PCA9541_CTL_NBUSON) >> 1); +} + +/* + * Arbitration is defined as a two-step process. A bus master can only activate + * the slave bus if it owns it; otherwise it has to request ownership first. + * This multi-step process ensures that access contention is resolved + * gracefully. + * + * Bus	Ownership	Other master	Action + * state		requested access + * ---------------------------------------------------- + * off	-		yes		wait for arbitration timeout or + *					for other master to drop request + * off	no		no		take ownership + * off	yes		no		turn on bus + * on	yes		-		done + * on	no		-		wait for arbitration timeout or + *					for other master to release bus + * + * The main contention point occurs if the slave bus is off and both masters + * request ownership at the same time. In this case, one master will turn on + * the slave bus, believing that it owns it. The other master will request + * bus ownership. Result is that the bus is turned on, and master which did + * _not_ own the slave bus before ends up owning it. + */ + +/* Control commands per PCA9541 datasheet */ +static const u8 pca9541_control[16] = { +	4, 0, 1, 5, 4, 4, 5, 5, 0, 0, 1, 1, 0, 4, 5, 1 +}; + +/* + * Channel arbitration + * + * Return values: + *  <0: error + *  0 : bus not acquired + *  1 : bus acquired + */ +static int pca9541_arbitrate(struct i2c_client *client) +{ +	struct pca9541 *data = i2c_get_clientdata(client); +	int reg; + +	reg = pca9541_reg_read(client, PCA9541_CONTROL); +	if (reg < 0) +		return reg; + +	if (busoff(reg)) { +		int istat; +		/* +		 * Bus is off. Request ownership or turn it on unless +		 * other master requested ownership. +		 */ +		istat = pca9541_reg_read(client, PCA9541_ISTAT); +		if (!(istat & PCA9541_ISTAT_NMYTEST) +		    || time_is_before_eq_jiffies(data->arb_timeout)) { +			/* +			 * Other master did not request ownership, +			 * or arbitration timeout expired. Take the bus. +			 */ +			pca9541_reg_write(client, +					  PCA9541_CONTROL, +					  pca9541_control[reg & 0x0f] +					  | PCA9541_CTL_NTESTON); +			data->select_timeout = SELECT_DELAY_SHORT; +		} else { +			/* +			 * Other master requested ownership. +			 * Set extra long timeout to give it time to acquire it. +			 */ +			data->select_timeout = SELECT_DELAY_LONG * 2; +		} +	} else if (mybus(reg)) { +		/* +		 * Bus is on, and we own it. We are done with acquisition. +		 * Reset NTESTON and BUSINIT, then return success. +		 */ +		if (reg & (PCA9541_CTL_NTESTON | PCA9541_CTL_BUSINIT)) +			pca9541_reg_write(client, +					  PCA9541_CONTROL, +					  reg & ~(PCA9541_CTL_NTESTON +						  | PCA9541_CTL_BUSINIT)); +		return 1; +	} else { +		/* +		 * Other master owns the bus. +		 * If arbitration timeout has expired, force ownership. +		 * Otherwise request it. +		 */ +		data->select_timeout = SELECT_DELAY_LONG; +		if (time_is_before_eq_jiffies(data->arb_timeout)) { +			/* Time is up, take the bus and reset it. */ +			pca9541_reg_write(client, +					  PCA9541_CONTROL, +					  pca9541_control[reg & 0x0f] +					  | PCA9541_CTL_BUSINIT +					  | PCA9541_CTL_NTESTON); +		} else { +			/* Request bus ownership if needed */ +			if (!(reg & PCA9541_CTL_NTESTON)) +				pca9541_reg_write(client, +						  PCA9541_CONTROL, +						  reg | PCA9541_CTL_NTESTON); +		} +	} +	return 0; +} + +static int pca9541_select_chan(struct i2c_adapter *adap, void *client, u32 chan) +{ +	struct pca9541 *data = i2c_get_clientdata(client); +	int ret; +	unsigned long timeout = jiffies + ARB2_TIMEOUT; +		/* give up after this time */ + +	data->arb_timeout = jiffies + ARB_TIMEOUT; +		/* force bus ownership after this time */ + +	do { +		ret = pca9541_arbitrate(client); +		if (ret) +			return ret < 0 ? ret : 0; + +		if (data->select_timeout == SELECT_DELAY_SHORT) +			udelay(data->select_timeout); +		else +			msleep(data->select_timeout / 1000); +	} while (time_is_after_eq_jiffies(timeout)); + +	return -ETIMEDOUT; +} + +static int pca9541_release_chan(struct i2c_adapter *adap, +				void *client, u32 chan) +{ +	pca9541_release_bus(client); +	return 0; +} + +/* + * I2C init/probing/exit functions + */ +static int pca9541_probe(struct i2c_client *client, +			 const struct i2c_device_id *id) +{ +	struct i2c_adapter *adap = client->adapter; +	struct pca954x_platform_data *pdata = client->dev.platform_data; +	struct pca9541 *data; +	int force; +	int ret = -ENODEV; + +	if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_BYTE_DATA)) +		goto err; + +	data = kzalloc(sizeof(struct pca9541), GFP_KERNEL); +	if (!data) { +		ret = -ENOMEM; +		goto err; +	} + +	i2c_set_clientdata(client, data); + +	/* +	 * I2C accesses are unprotected here. +	 * We have to lock the adapter before releasing the bus. +	 */ +	i2c_lock_adapter(adap); +	pca9541_release_bus(client); +	i2c_unlock_adapter(adap); + +	/* Create mux adapter */ + +	force = 0; +	if (pdata) +		force = pdata->modes[0].adap_id; +	data->mux_adap = i2c_add_mux_adapter(adap, client, force, 0, +					     pca9541_select_chan, +					     pca9541_release_chan); + +	if (data->mux_adap == NULL) { +		dev_err(&client->dev, "failed to register master selector\n"); +		goto exit_free; +	} + +	dev_info(&client->dev, "registered master selector for I2C %s\n", +		 client->name); + +	return 0; + +exit_free: +	kfree(data); +err: +	return ret; +} + +static int pca9541_remove(struct i2c_client *client) +{ +	struct pca9541 *data = i2c_get_clientdata(client); + +	i2c_del_mux_adapter(data->mux_adap); + +	kfree(data); +	return 0; +} + +static struct i2c_driver pca9541_driver = { +	.driver = { +		   .name = "pca9541", +		   .owner = THIS_MODULE, +		   }, +	.probe = pca9541_probe, +	.remove = pca9541_remove, +	.id_table = pca9541_id, +}; + +static int __init pca9541_init(void) +{ +	return i2c_add_driver(&pca9541_driver); +} + +static void __exit pca9541_exit(void) +{ +	i2c_del_driver(&pca9541_driver); +} + +module_init(pca9541_init); +module_exit(pca9541_exit); + +MODULE_AUTHOR("Guenter Roeck <guenter.roeck@ericsson.com>"); +MODULE_DESCRIPTION("PCA9541 I2C master selector driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/i2c/muxes/pca954x.c b/drivers/i2c/muxes/pca954x.c new file mode 100644 index 00000000000..54e1ce73534 --- /dev/null +++ b/drivers/i2c/muxes/pca954x.c @@ -0,0 +1,301 @@ +/* + * I2C multiplexer + * + * Copyright (c) 2008-2009 Rodolfo Giometti <giometti@linux.it> + * Copyright (c) 2008-2009 Eurotech S.p.A. <info@eurotech.it> + * + * This module supports the PCA954x series of I2C multiplexer/switch chips + * made by Philips Semiconductors. + * This includes the: + *	 PCA9540, PCA9542, PCA9543, PCA9544, PCA9545, PCA9546, PCA9547 + *	 and PCA9548. + * + * These chips are all controlled via the I2C bus itself, and all have a + * single 8-bit register. The upstream "parent" bus fans out to two, + * four, or eight downstream busses or channels; which of these + * are selected is determined by the chip type and register contents. A + * mux can select only one sub-bus at a time; a switch can select any + * combination simultaneously. + * + * Based on: + *	pca954x.c from Kumar Gala <galak@kernel.crashing.org> + * Copyright (C) 2006 + * + * Based on: + *	pca954x.c from Ken Harrenstien + * Copyright (C) 2004 Google, Inc. (Ken Harrenstien) + * + * Based on: + *	i2c-virtual_cb.c from Brian Kuschak <bkuschak@yahoo.com> + * and + *	pca9540.c from Jean Delvare <khali@linux-fr.org>. + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include <linux/module.h> +#include <linux/init.h> +#include <linux/slab.h> +#include <linux/device.h> +#include <linux/i2c.h> +#include <linux/i2c-mux.h> + +#include <linux/i2c/pca954x.h> + +#define PCA954X_MAX_NCHANS 8 + +enum pca_type { +	pca_9540, +	pca_9542, +	pca_9543, +	pca_9544, +	pca_9545, +	pca_9546, +	pca_9547, +	pca_9548, +}; + +struct pca954x { +	enum pca_type type; +	struct i2c_adapter *virt_adaps[PCA954X_MAX_NCHANS]; + +	u8 last_chan;		/* last register value */ +}; + +struct chip_desc { +	u8 nchans; +	u8 enable;	/* used for muxes only */ +	enum muxtype { +		pca954x_ismux = 0, +		pca954x_isswi +	} muxtype; +}; + +/* Provide specs for the PCA954x types we know about */ +static const struct chip_desc chips[] = { +	[pca_9540] = { +		.nchans = 2, +		.enable = 0x4, +		.muxtype = pca954x_ismux, +	}, +	[pca_9543] = { +		.nchans = 2, +		.muxtype = pca954x_isswi, +	}, +	[pca_9544] = { +		.nchans = 4, +		.enable = 0x4, +		.muxtype = pca954x_ismux, +	}, +	[pca_9545] = { +		.nchans = 4, +		.muxtype = pca954x_isswi, +	}, +	[pca_9547] = { +		.nchans = 8, +		.enable = 0x8, +		.muxtype = pca954x_ismux, +	}, +	[pca_9548] = { +		.nchans = 8, +		.muxtype = pca954x_isswi, +	}, +}; + +static const struct i2c_device_id pca954x_id[] = { +	{ "pca9540", pca_9540 }, +	{ "pca9542", pca_9540 }, +	{ "pca9543", pca_9543 }, +	{ "pca9544", pca_9544 }, +	{ "pca9545", pca_9545 }, +	{ "pca9546", pca_9545 }, +	{ "pca9547", pca_9547 }, +	{ "pca9548", pca_9548 }, +	{ } +}; +MODULE_DEVICE_TABLE(i2c, pca954x_id); + +/* Write to mux register. Don't use i2c_transfer()/i2c_smbus_xfer() +   for this as they will try to lock adapter a second time */ +static int pca954x_reg_write(struct i2c_adapter *adap, +			     struct i2c_client *client, u8 val) +{ +	int ret = -ENODEV; + +	if (adap->algo->master_xfer) { +		struct i2c_msg msg; +		char buf[1]; + +		msg.addr = client->addr; +		msg.flags = 0; +		msg.len = 1; +		buf[0] = val; +		msg.buf = buf; +		ret = adap->algo->master_xfer(adap, &msg, 1); +	} else { +		union i2c_smbus_data data; +		ret = adap->algo->smbus_xfer(adap, client->addr, +					     client->flags, +					     I2C_SMBUS_WRITE, +					     val, I2C_SMBUS_BYTE, &data); +	} + +	return ret; +} + +static int pca954x_select_chan(struct i2c_adapter *adap, +			       void *client, u32 chan) +{ +	struct pca954x *data = i2c_get_clientdata(client); +	const struct chip_desc *chip = &chips[data->type]; +	u8 regval; +	int ret = 0; + +	/* we make switches look like muxes, not sure how to be smarter */ +	if (chip->muxtype == pca954x_ismux) +		regval = chan | chip->enable; +	else +		regval = 1 << chan; + +	/* Only select the channel if its different from the last channel */ +	if (data->last_chan != regval) { +		ret = pca954x_reg_write(adap, client, regval); +		data->last_chan = regval; +	} + +	return ret; +} + +static int pca954x_deselect_mux(struct i2c_adapter *adap, +				void *client, u32 chan) +{ +	struct pca954x *data = i2c_get_clientdata(client); + +	/* Deselect active channel */ +	data->last_chan = 0; +	return pca954x_reg_write(adap, client, data->last_chan); +} + +/* + * I2C init/probing/exit functions + */ +static int pca954x_probe(struct i2c_client *client, +			 const struct i2c_device_id *id) +{ +	struct i2c_adapter *adap = to_i2c_adapter(client->dev.parent); +	struct pca954x_platform_data *pdata = client->dev.platform_data; +	int num, force; +	struct pca954x *data; +	int ret = -ENODEV; + +	if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_BYTE)) +		goto err; + +	data = kzalloc(sizeof(struct pca954x), GFP_KERNEL); +	if (!data) { +		ret = -ENOMEM; +		goto err; +	} + +	i2c_set_clientdata(client, data); + +	/* Read the mux register at addr to verify +	 * that the mux is in fact present. +	 */ +	if (i2c_smbus_read_byte(client) < 0) { +		dev_warn(&client->dev, "probe failed\n"); +		goto exit_free; +	} + +	data->type = id->driver_data; +	data->last_chan = 0;		   /* force the first selection */ + +	/* Now create an adapter for each channel */ +	for (num = 0; num < chips[data->type].nchans; num++) { +		force = 0;			  /* dynamic adap number */ +		if (pdata) { +			if (num < pdata->num_modes) +				/* force static number */ +				force = pdata->modes[num].adap_id; +			else +				/* discard unconfigured channels */ +				break; +		} + +		data->virt_adaps[num] = +			i2c_add_mux_adapter(adap, client, +				force, num, pca954x_select_chan, +				(pdata && pdata->modes[num].deselect_on_exit) +					? pca954x_deselect_mux : NULL); + +		if (data->virt_adaps[num] == NULL) { +			ret = -ENODEV; +			dev_err(&client->dev, +				"failed to register multiplexed adapter" +				" %d as bus %d\n", num, force); +			goto virt_reg_failed; +		} +	} + +	dev_info(&client->dev, +		 "registered %d multiplexed busses for I2C %s %s\n", +		 num, chips[data->type].muxtype == pca954x_ismux +				? "mux" : "switch", client->name); + +	return 0; + +virt_reg_failed: +	for (num--; num >= 0; num--) +		i2c_del_mux_adapter(data->virt_adaps[num]); +exit_free: +	kfree(data); +err: +	return ret; +} + +static int pca954x_remove(struct i2c_client *client) +{ +	struct pca954x *data = i2c_get_clientdata(client); +	const struct chip_desc *chip = &chips[data->type]; +	int i, err; + +	for (i = 0; i < chip->nchans; ++i) +		if (data->virt_adaps[i]) { +			err = i2c_del_mux_adapter(data->virt_adaps[i]); +			if (err) +				return err; +			data->virt_adaps[i] = NULL; +		} + +	kfree(data); +	return 0; +} + +static struct i2c_driver pca954x_driver = { +	.driver		= { +		.name	= "pca954x", +		.owner	= THIS_MODULE, +	}, +	.probe		= pca954x_probe, +	.remove		= pca954x_remove, +	.id_table	= pca954x_id, +}; + +static int __init pca954x_init(void) +{ +	return i2c_add_driver(&pca954x_driver); +} + +static void __exit pca954x_exit(void) +{ +	i2c_del_driver(&pca954x_driver); +} + +module_init(pca954x_init); +module_exit(pca954x_exit); + +MODULE_AUTHOR("Rodolfo Giometti <giometti@linux.it>"); +MODULE_DESCRIPTION("PCA954x I2C mux/switch driver"); +MODULE_LICENSE("GPL v2"); | 
