diff options
Diffstat (limited to 'drivers/i2c/busses/i2c-omap.c')
-rw-r--r-- | drivers/i2c/busses/i2c-omap.c | 258 |
1 files changed, 147 insertions, 111 deletions
diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index db31eaed6ea..7a62acb7d26 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c @@ -43,15 +43,16 @@ #include <linux/slab.h> #include <linux/i2c-omap.h> #include <linux/pm_runtime.h> -#include <linux/pm_qos.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)) @@ -187,10 +188,10 @@ struct omap_i2c_dev { int reg_shift; /* bit shift for I2C register addresses */ struct completion cmd_complete; struct resource *ioarea; - u32 latency; /* maximum MPU wkup latency */ - struct pm_qos_request pm_qos_request; + u32 latency; /* maximum mpu wkup latency */ + 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_AUTOIDLE_MASK); - - } 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)); - - 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); - } + omap_i2c_write_reg(dev, OMAP_I2C_SYSC_REG, sysc); + + } + return 0; +} + +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; + + 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,11 +500,13 @@ 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 */ - dev->latency = (1000000 * dev->threshold) / (1000 * dev->speed / 8); + if (dev->set_mpu_wkup_lat != NULL) + dev->latency = (1000000 * dev->threshold) / + (1000 * dev->speed / 8); } /* @@ -522,6 +534,9 @@ static int omap_i2c_xfer_msg(struct i2c_adapter *adap, dev->buf = msg->buf; dev->buf_len = msg->len; + /* make sure writes to dev->buf_len are ordered */ + barrier(); + omap_i2c_write_reg(dev, OMAP_I2C_CNT_REG, dev->buf_len); /* Clear the FIFO Buffers */ @@ -579,10 +594,10 @@ static int omap_i2c_xfer_msg(struct i2c_adapter *adap, */ timeout = wait_for_completion_timeout(&dev->cmd_complete, OMAP_I2C_TIMEOUT); - dev->buf_len = 0; 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; } @@ -592,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; } @@ -629,16 +645,8 @@ omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) if (r < 0) goto out; - /* - * When waiting for completion of a i2c transfer, we need to - * set a wake up latency constraint for the MPU. This is to - * ensure quick enough wakeup from idle, when transfer - * completes. - */ - if (dev->latency) - pm_qos_add_request(&dev->pm_qos_request, - PM_QOS_CPU_DMA_LATENCY, - dev->latency); + if (dev->set_mpu_wkup_lat != NULL) + dev->set_mpu_wkup_lat(dev->dev, dev->latency); for (i = 0; i < num; i++) { r = omap_i2c_xfer_msg(adap, &msgs[i], (i == (num - 1))); @@ -646,13 +654,14 @@ omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) break; } - if (dev->latency) - pm_qos_remove_request(&dev->pm_qos_request); - 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); @@ -1029,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 = { @@ -1052,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) { @@ -1064,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); @@ -1095,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); @@ -1104,7 +1122,17 @@ omap_i2c_probe(struct platform_device *pdev) } else if (pdata != NULL) { dev->speed = pdata->clkrate; dev->flags = pdata->flags; - dev->dtrev = pdata->rev; + dev->set_mpu_wkup_lat = pdata->set_mpu_wkup_lat; + } + + 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; @@ -1117,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); @@ -1130,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) @@ -1155,12 +1204,13 @@ 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 */ - dev->latency = (1000000 * dev->fifo_size) / - (1000 * dev->speed / 8); + if (dev->set_mpu_wkup_lat != NULL) + dev->latency = (1000000 * dev->fifo_size) / + (1000 * dev->speed / 8); } /* reset ASAP, clearing any IRQs */ @@ -1197,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); @@ -1241,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); @@ -1264,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; } |