diff options
Diffstat (limited to 'drivers/i2c/busses/i2c-omap.c')
| -rw-r--r-- | drivers/i2c/busses/i2c-omap.c | 220 | 
1 files changed, 129 insertions, 91 deletions
diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index 3525c9e62cb..7a62acb7d26 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c @@ -43,14 +43,16 @@  #include <linux/slab.h>  #include <linux/i2c-omap.h>  #include <linux/pm_runtime.h> +#include <linux/pinctrl/consumer.h>  /* I2C controller revisions */  #define OMAP_I2C_OMAP1_REV_2		0x20  /* I2C controller revisions present on specific hardware */ -#define OMAP_I2C_REV_ON_2430		0x36 -#define OMAP_I2C_REV_ON_3430_3530	0x3C -#define OMAP_I2C_REV_ON_3630_4430	0x40 +#define OMAP_I2C_REV_ON_2430		0x00000036 +#define OMAP_I2C_REV_ON_3430_3530	0x0000003C +#define OMAP_I2C_REV_ON_3630		0x00000040 +#define OMAP_I2C_REV_ON_4430_PLUS	0x50400002  /* timeout waiting for the controller to respond */  #define OMAP_I2C_TIMEOUT (msecs_to_jiffies(1000)) @@ -190,7 +192,6 @@ struct omap_i2c_dev {  	void			(*set_mpu_wkup_lat)(struct device *dev,  						    long latency);  	u32			speed;		/* Speed of bus in kHz */ -	u32			dtrev;		/* extra revision from DT */  	u32			flags;  	u16			cmd_err;  	u8			*buf; @@ -202,17 +203,18 @@ struct omap_i2c_dev {  						 * fifo_size==0 implies no fifo  						 * if set, should be trsh+1  						 */ -	u8			rev; +	u32			rev;  	unsigned		b_hw:1;		/* bad h/w fixes */  	unsigned		receiver:1;	/* true when we're in receiver mode */  	u16			iestate;	/* Saved interrupt register */  	u16			pscstate;  	u16			scllstate;  	u16			sclhstate; -	u16			bufstate;  	u16			syscstate;  	u16			westate;  	u16			errata; + +	struct pinctrl		*pins;  };  static const u8 reg_map_ip_v1[] = { @@ -275,16 +277,39 @@ static inline u16 omap_i2c_read_reg(struct omap_i2c_dev *i2c_dev, int reg)  				(i2c_dev->regs[reg] << i2c_dev->reg_shift));  } -static int omap_i2c_init(struct omap_i2c_dev *dev) +static void __omap_i2c_init(struct omap_i2c_dev *dev) +{ + +	omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0); + +	/* Setup clock prescaler to obtain approx 12MHz I2C module clock: */ +	omap_i2c_write_reg(dev, OMAP_I2C_PSC_REG, dev->pscstate); + +	/* SCL low and high time values */ +	omap_i2c_write_reg(dev, OMAP_I2C_SCLL_REG, dev->scllstate); +	omap_i2c_write_reg(dev, OMAP_I2C_SCLH_REG, dev->sclhstate); +	if (dev->rev >= OMAP_I2C_REV_ON_3430_3530) +		omap_i2c_write_reg(dev, OMAP_I2C_WE_REG, dev->westate); + +	/* Take the I2C module out of reset: */ +	omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, OMAP_I2C_CON_EN); + +	/* +	 * Don't write to this register if the IE state is 0 as it can +	 * cause deadlock. +	 */ +	if (dev->iestate) +		omap_i2c_write_reg(dev, OMAP_I2C_IE_REG, dev->iestate); +} + +static int omap_i2c_reset(struct omap_i2c_dev *dev)  { -	u16 psc = 0, scll = 0, sclh = 0, buf = 0; -	u16 fsscll = 0, fssclh = 0, hsscll = 0, hssclh = 0; -	unsigned long fclk_rate = 12000000;  	unsigned long timeout; -	unsigned long internal_clk = 0; -	struct clk *fclk; +	u16 sysc;  	if (dev->rev >= OMAP_I2C_OMAP1_REV_2) { +		sysc = omap_i2c_read_reg(dev, OMAP_I2C_SYSC_REG); +  		/* Disable I2C controller before soft reset */  		omap_i2c_write_reg(dev, OMAP_I2C_CON_REG,  			omap_i2c_read_reg(dev, OMAP_I2C_CON_REG) & @@ -306,32 +331,28 @@ static int omap_i2c_init(struct omap_i2c_dev *dev)  		}  		/* SYSC register is cleared by the reset; rewrite it */ -		if (dev->rev == OMAP_I2C_REV_ON_2430) { +		omap_i2c_write_reg(dev, OMAP_I2C_SYSC_REG, sysc); -			omap_i2c_write_reg(dev, OMAP_I2C_SYSC_REG, -					   SYSC_AUTOIDLE_MASK); +	} +	return 0; +} -		} else if (dev->rev >= OMAP_I2C_REV_ON_3430_3530) { -			dev->syscstate = SYSC_AUTOIDLE_MASK; -			dev->syscstate |= SYSC_ENAWAKEUP_MASK; -			dev->syscstate |= (SYSC_IDLEMODE_SMART << -			      __ffs(SYSC_SIDLEMODE_MASK)); -			dev->syscstate |= (SYSC_CLOCKACTIVITY_FCLK << -			      __ffs(SYSC_CLOCKACTIVITY_MASK)); +static int omap_i2c_init(struct omap_i2c_dev *dev) +{ +	u16 psc = 0, scll = 0, sclh = 0; +	u16 fsscll = 0, fssclh = 0, hsscll = 0, hssclh = 0; +	unsigned long fclk_rate = 12000000; +	unsigned long internal_clk = 0; +	struct clk *fclk; -			omap_i2c_write_reg(dev, OMAP_I2C_SYSC_REG, -							dev->syscstate); -			/* -			 * Enabling all wakup sources to stop I2C freezing on -			 * WFI instruction. -			 * REVISIT: Some wkup sources might not be needed. -			 */ -			dev->westate = OMAP_I2C_WE_ALL; -			omap_i2c_write_reg(dev, OMAP_I2C_WE_REG, -							dev->westate); -		} +	if (dev->rev >= OMAP_I2C_REV_ON_3430_3530) { +		/* +		 * Enabling all wakup sources to stop I2C freezing on +		 * WFI instruction. +		 * REVISIT: Some wkup sources might not be needed. +		 */ +		dev->westate = OMAP_I2C_WE_ALL;  	} -	omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0);  	if (dev->flags & OMAP_I2C_FLAG_ALWAYS_ARMXOR_CLK) {  		/* @@ -416,28 +437,17 @@ static int omap_i2c_init(struct omap_i2c_dev *dev)  		sclh = fclk_rate / (dev->speed * 2) - 7 + psc;  	} -	/* Setup clock prescaler to obtain approx 12MHz I2C module clock: */ -	omap_i2c_write_reg(dev, OMAP_I2C_PSC_REG, psc); - -	/* SCL low and high time values */ -	omap_i2c_write_reg(dev, OMAP_I2C_SCLL_REG, scll); -	omap_i2c_write_reg(dev, OMAP_I2C_SCLH_REG, sclh); - -	/* Take the I2C module out of reset: */ -	omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, OMAP_I2C_CON_EN); - -	/* Enable interrupts */  	dev->iestate = (OMAP_I2C_IE_XRDY | OMAP_I2C_IE_RRDY |  			OMAP_I2C_IE_ARDY | OMAP_I2C_IE_NACK |  			OMAP_I2C_IE_AL)  | ((dev->fifo_size) ?  				(OMAP_I2C_IE_RDR | OMAP_I2C_IE_XDR) : 0); -	omap_i2c_write_reg(dev, OMAP_I2C_IE_REG, dev->iestate); -	if (dev->flags & OMAP_I2C_FLAG_RESET_REGS_POSTIDLE) { -		dev->pscstate = psc; -		dev->scllstate = scll; -		dev->sclhstate = sclh; -		dev->bufstate = buf; -	} + +	dev->pscstate = psc; +	dev->scllstate = scll; +	dev->sclhstate = sclh; + +	__omap_i2c_init(dev); +  	return 0;  } @@ -490,7 +500,7 @@ static void omap_i2c_resize_fifo(struct omap_i2c_dev *dev, u8 size, bool is_rx)  	omap_i2c_write_reg(dev, OMAP_I2C_BUF_REG, buf); -	if (dev->rev < OMAP_I2C_REV_ON_3630_4430) +	if (dev->rev < OMAP_I2C_REV_ON_3630)  		dev->b_hw = 1; /* Enable hardware fixes */  	/* calculate wakeup latency constraint for MPU */ @@ -586,7 +596,8 @@ static int omap_i2c_xfer_msg(struct i2c_adapter *adap,  						OMAP_I2C_TIMEOUT);  	if (timeout == 0) {  		dev_err(dev->dev, "controller timed out\n"); -		omap_i2c_init(dev); +		omap_i2c_reset(dev); +		__omap_i2c_init(dev);  		return -ETIMEDOUT;  	} @@ -596,7 +607,8 @@ static int omap_i2c_xfer_msg(struct i2c_adapter *adap,  	/* We have an error */  	if (dev->cmd_err & (OMAP_I2C_STAT_AL | OMAP_I2C_STAT_ROVR |  			    OMAP_I2C_STAT_XUDF)) { -		omap_i2c_init(dev); +		omap_i2c_reset(dev); +		__omap_i2c_init(dev);  		return -EIO;  	} @@ -642,13 +654,14 @@ omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)  			break;  	} -	if (dev->set_mpu_wkup_lat != NULL) -		dev->set_mpu_wkup_lat(dev->dev, -1); -  	if (r == 0)  		r = num;  	omap_i2c_wait_for_bb(dev); + +	if (dev->set_mpu_wkup_lat != NULL) +		dev->set_mpu_wkup_lat(dev->dev, -1); +  out:  	pm_runtime_mark_last_busy(dev->dev);  	pm_runtime_put_autosuspend(dev->dev); @@ -1025,9 +1038,7 @@ static const struct i2c_algorithm omap_i2c_algo = {  #ifdef CONFIG_OF  static struct omap_i2c_bus_platform_data omap3_pdata = {  	.rev = OMAP_I2C_IP_VERSION_1, -	.flags = OMAP_I2C_FLAG_APPLY_ERRATA_I207 | -		 OMAP_I2C_FLAG_RESET_REGS_POSTIDLE | -		 OMAP_I2C_FLAG_BUS_SHIFT_2, +	.flags = OMAP_I2C_FLAG_BUS_SHIFT_2,  };  static struct omap_i2c_bus_platform_data omap4_pdata = { @@ -1048,6 +1059,16 @@ static const struct of_device_id omap_i2c_of_match[] = {  MODULE_DEVICE_TABLE(of, omap_i2c_of_match);  #endif +#define OMAP_I2C_SCHEME(rev)		((rev & 0xc000) >> 14) + +#define OMAP_I2C_REV_SCHEME_0_MAJOR(rev) (rev >> 4) +#define OMAP_I2C_REV_SCHEME_0_MINOR(rev) (rev & 0xf) + +#define OMAP_I2C_REV_SCHEME_1_MAJOR(rev) ((rev & 0x0700) >> 7) +#define OMAP_I2C_REV_SCHEME_1_MINOR(rev) (rev & 0x1f) +#define OMAP_I2C_SCHEME_0		0 +#define OMAP_I2C_SCHEME_1		1 +  static int __devinit  omap_i2c_probe(struct platform_device *pdev)  { @@ -1060,6 +1081,8 @@ omap_i2c_probe(struct platform_device *pdev)  	const struct of_device_id *match;  	int irq;  	int r; +	u32 rev; +	u16 minor, major, scheme;  	/* NOTE: driver uses the static register mapping */  	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); @@ -1091,7 +1114,6 @@ omap_i2c_probe(struct platform_device *pdev)  		u32 freq = 100000; /* default to 100000 Hz */  		pdata = match->data; -		dev->dtrev = pdata->rev;  		dev->flags = pdata->flags;  		of_property_read_u32(node, "clock-frequency", &freq); @@ -1101,7 +1123,16 @@ omap_i2c_probe(struct platform_device *pdev)  		dev->speed = pdata->clkrate;  		dev->flags = pdata->flags;  		dev->set_mpu_wkup_lat = pdata->set_mpu_wkup_lat; -		dev->dtrev = pdata->rev; +	} + +	dev->pins = devm_pinctrl_get_select_default(&pdev->dev); +	if (IS_ERR(dev->pins)) { +		if (PTR_ERR(dev->pins) == -EPROBE_DEFER) +			return -EPROBE_DEFER; + +		dev_warn(&pdev->dev, "did not get pins for i2c error: %li\n", +			 PTR_ERR(dev->pins)); +		dev->pins = NULL;  	}  	dev->dev = &pdev->dev; @@ -1114,11 +1145,6 @@ omap_i2c_probe(struct platform_device *pdev)  	dev->reg_shift = (dev->flags >> OMAP_I2C_FLAG_BUS_SHIFT__SHIFT) & 3; -	if (dev->dtrev == OMAP_I2C_IP_VERSION_2) -		dev->regs = (u8 *)reg_map_ip_v2; -	else -		dev->regs = (u8 *)reg_map_ip_v1; -  	pm_runtime_enable(dev->dev);  	pm_runtime_set_autosuspend_delay(dev->dev, OMAP_I2C_PM_TIMEOUT);  	pm_runtime_use_autosuspend(dev->dev); @@ -1127,11 +1153,37 @@ omap_i2c_probe(struct platform_device *pdev)  	if (IS_ERR_VALUE(r))  		goto err_free_mem; -	dev->rev = omap_i2c_read_reg(dev, OMAP_I2C_REV_REG) & 0xff; +	/* +	 * Read the Rev hi bit-[15:14] ie scheme this is 1 indicates ver2. +	 * On omap1/3/2 Offset 4 is IE Reg the bit [15:14] is 0 at reset. +	 * Also since the omap_i2c_read_reg uses reg_map_ip_* a +	 * raw_readw is done. +	 */ +	rev = __raw_readw(dev->base + 0x04); + +	scheme = OMAP_I2C_SCHEME(rev); +	switch (scheme) { +	case OMAP_I2C_SCHEME_0: +		dev->regs = (u8 *)reg_map_ip_v1; +		dev->rev = omap_i2c_read_reg(dev, OMAP_I2C_REV_REG); +		minor = OMAP_I2C_REV_SCHEME_0_MAJOR(dev->rev); +		major = OMAP_I2C_REV_SCHEME_0_MAJOR(dev->rev); +		break; +	case OMAP_I2C_SCHEME_1: +		/* FALLTHROUGH */ +	default: +		dev->regs = (u8 *)reg_map_ip_v2; +		rev = (rev << 16) | +			omap_i2c_read_reg(dev, OMAP_I2C_IP_V2_REVNB_LO); +		minor = OMAP_I2C_REV_SCHEME_1_MINOR(rev); +		major = OMAP_I2C_REV_SCHEME_1_MAJOR(rev); +		dev->rev = rev; +	}  	dev->errata = 0; -	if (dev->flags & OMAP_I2C_FLAG_APPLY_ERRATA_I207) +	if (dev->rev >= OMAP_I2C_REV_ON_2430 && +			dev->rev < OMAP_I2C_REV_ON_4430_PLUS)  		dev->errata |= I2C_OMAP_ERRATA_I207;  	if (dev->rev <= OMAP_I2C_REV_ON_3430_3530) @@ -1152,7 +1204,7 @@ omap_i2c_probe(struct platform_device *pdev)  		dev->fifo_size = (dev->fifo_size / 2); -		if (dev->rev < OMAP_I2C_REV_ON_3630_4430) +		if (dev->rev < OMAP_I2C_REV_ON_3630)  			dev->b_hw = 1; /* Enable hardware fixes */  		/* calculate wakeup latency constraint for MPU */ @@ -1195,8 +1247,8 @@ omap_i2c_probe(struct platform_device *pdev)  		goto err_unuse_clocks;  	} -	dev_info(dev->dev, "bus %d rev%d.%d.%d at %d kHz\n", adap->nr, -		 dev->dtrev, dev->rev >> 4, dev->rev & 0xf, dev->speed); +	dev_info(dev->dev, "bus %d rev%d.%d at %d kHz\n", adap->nr, +		 major, minor, dev->speed);  	of_i2c_register_devices(adap); @@ -1239,14 +1291,13 @@ static int omap_i2c_runtime_suspend(struct device *dev)  {  	struct platform_device *pdev = to_platform_device(dev);  	struct omap_i2c_dev *_dev = platform_get_drvdata(pdev); -	u16 iv;  	_dev->iestate = omap_i2c_read_reg(_dev, OMAP_I2C_IE_REG);  	omap_i2c_write_reg(_dev, OMAP_I2C_IE_REG, 0);  	if (_dev->rev < OMAP_I2C_OMAP1_REV_2) { -		iv = omap_i2c_read_reg(_dev, OMAP_I2C_IV_REG); /* Read clears */ +		omap_i2c_read_reg(_dev, OMAP_I2C_IV_REG); /* Read clears */  	} else {  		omap_i2c_write_reg(_dev, OMAP_I2C_STAT_REG, _dev->iestate); @@ -1262,23 +1313,10 @@ static int omap_i2c_runtime_resume(struct device *dev)  	struct platform_device *pdev = to_platform_device(dev);  	struct omap_i2c_dev *_dev = platform_get_drvdata(pdev); -	if (_dev->flags & OMAP_I2C_FLAG_RESET_REGS_POSTIDLE) { -		omap_i2c_write_reg(_dev, OMAP_I2C_CON_REG, 0); -		omap_i2c_write_reg(_dev, OMAP_I2C_PSC_REG, _dev->pscstate); -		omap_i2c_write_reg(_dev, OMAP_I2C_SCLL_REG, _dev->scllstate); -		omap_i2c_write_reg(_dev, OMAP_I2C_SCLH_REG, _dev->sclhstate); -		omap_i2c_write_reg(_dev, OMAP_I2C_BUF_REG, _dev->bufstate); -		omap_i2c_write_reg(_dev, OMAP_I2C_SYSC_REG, _dev->syscstate); -		omap_i2c_write_reg(_dev, OMAP_I2C_WE_REG, _dev->westate); -		omap_i2c_write_reg(_dev, OMAP_I2C_CON_REG, OMAP_I2C_CON_EN); -	} +	if (!_dev->regs) +		return 0; -	/* -	 * Don't write to this register if the IE state is 0 as it can -	 * cause deadlock. -	 */ -	if (_dev->iestate) -		omap_i2c_write_reg(_dev, OMAP_I2C_IE_REG, _dev->iestate); +	__omap_i2c_init(_dev);  	return 0;  }  |