diff options
Diffstat (limited to 'drivers/i2c')
| -rw-r--r-- | drivers/i2c/busses/i2c-i801.c | 8 | ||||
| -rw-r--r-- | drivers/i2c/busses/i2c-mpc.c | 69 | ||||
| -rw-r--r-- | drivers/i2c/busses/i2c-sibyte.c | 4 | ||||
| -rw-r--r-- | drivers/i2c/i2c-core.c | 7 | 
4 files changed, 54 insertions, 34 deletions
diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index f4b21f2bb8e..c60081169cc 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c @@ -655,7 +655,7 @@ static void __devinit dmi_check_onboard_device(u8 type, const char *name,  		/* & ~0x80, ignore enabled/disabled bit */  		if ((type & ~0x80) != dmi_devices[i].type)  			continue; -		if (strcmp(name, dmi_devices[i].name)) +		if (strcasecmp(name, dmi_devices[i].name))  			continue;  		memset(&info, 0, sizeof(struct i2c_board_info)); @@ -704,9 +704,6 @@ static int __devinit i801_probe(struct pci_dev *dev,  {  	unsigned char temp;  	int err, i; -#if defined CONFIG_SENSORS_FSCHMD || defined CONFIG_SENSORS_FSCHMD_MODULE -	const char *vendor; -#endif  	I801_dev = dev;  	i801_features = 0; @@ -808,8 +805,7 @@ static int __devinit i801_probe(struct pci_dev *dev,  	}  #endif  #if defined CONFIG_SENSORS_FSCHMD || defined CONFIG_SENSORS_FSCHMD_MODULE -	vendor = dmi_get_system_info(DMI_BOARD_VENDOR); -	if (vendor && !strcmp(vendor, "FUJITSU SIEMENS")) +	if (dmi_name_in_vendors("FUJITSU"))  		dmi_walk(dmi_check_onboard_devices, &i801_adapter);  #endif diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c index df00eb1f11f..54247d475fc 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(); @@ -595,6 +612,14 @@ 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; diff --git a/drivers/i2c/busses/i2c-sibyte.c b/drivers/i2c/busses/i2c-sibyte.c index 3d76a188e42..0fe505d7abe 100644 --- a/drivers/i2c/busses/i2c-sibyte.c +++ b/drivers/i2c/busses/i2c-sibyte.c @@ -94,7 +94,7 @@ static int smbus_xfer(struct i2c_adapter *i2c_adap, u16 addr,  		}  		break;  	default: -		return -1;      /* XXXKW better error code? */ +		return -EOPNOTSUPP;  	}  	while (csr_in32(SMB_CSR(adap, R_SMB_STATUS)) & M_SMB_BUSY) @@ -104,7 +104,7 @@ static int smbus_xfer(struct i2c_adapter *i2c_adap, u16 addr,  	if (error & M_SMB_ERROR) {  		/* Clear error bit by writing a 1 */  		csr_out32(M_SMB_ERROR, SMB_CSR(adap, R_SMB_STATUS)); -		return -1;      /* XXXKW better error code? */ +		return (error & M_SMB_ERROR_TYPE) ? -EIO : -ENXIO;  	}  	if (data_bytes == 1) diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index 1cca2631e5b..0815e10da7c 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -1428,13 +1428,12 @@ static int i2c_detect(struct i2c_adapter *adapter, struct i2c_driver *driver)  	if (!(adapter->class & driver->class))  		goto exit_free; -	/* Stop here if we can't use SMBUS_QUICK */ -	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_QUICK)) { +	/* 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, "SMBus Quick command not supported, " -			 "can't probe for chips\n"); +		dev_warn(&adapter->dev, "Probing not supported\n");  		err = -EOPNOTSUPP;  		goto exit_free;  	}  |