diff options
author | Paul Walmsley <paul@pwsan.com> | 2008-11-21 16:39:55 -0500 |
---|---|---|
committer | Tony Lindgren <tony@atomide.com> | 2008-11-21 16:39:55 -0500 |
commit | fdd07fe6f6fe54250d8b1126b42ebdc72d938f05 (patch) | |
tree | 9f52a8091681f4c90eac953d5daacc378e6b2844 /drivers/i2c/busses/i2c-omap.c | |
parent | 9c76b878eb3f837ff98b37aa254e6cc7942e946b (diff) |
i2c-omap: reprogram OCP_SYSCONFIG register after reset
The I2C controller clears its OCP_SYSCONFIG register after an OCP soft reset.
Reprogram OCP_SYSCONFIG for maximum power savings on rev3.6 controllers
and beyond. On 2430, this involves setting the module AUTOIDLE bit.
On 3430, this includes module AUTOIDLE, wakeup enable, slave smart-idle,
and considers only the module functional clock state for idle-ack.
Boot-tested on 2430SDP and 3430SDP.
Signed-off-by: Paul Walmsley <paul@pwsan.com>
Cc: Richard Woodruff <r-woodruff2@ti.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>
Diffstat (limited to 'drivers/i2c/busses/i2c-omap.c')
-rw-r--r-- | drivers/i2c/busses/i2c-omap.c | 40 |
1 files changed, 34 insertions, 6 deletions
diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index 3ac510d9c9ba..b20235415878 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c | |||
@@ -123,11 +123,19 @@ | |||
123 | #define OMAP_I2C_SYSTEST_SDA_O (1 << 0) /* SDA line drive out */ | 123 | #define OMAP_I2C_SYSTEST_SDA_O (1 << 0) /* SDA line drive out */ |
124 | #endif | 124 | #endif |
125 | 125 | ||
126 | /* I2C System Status register (OMAP_I2C_SYSS): */ | 126 | /* OCP_SYSSTATUS bit definitions */ |
127 | #define OMAP_I2C_SYSS_RDONE (1 << 0) /* Reset Done */ | 127 | #define SYSS_RESETDONE_MASK (1 << 0) |
128 | |||
129 | /* OCP_SYSCONFIG bit definitions */ | ||
130 | #define SYSC_CLOCKACTIVITY_MASK (0x3 << 8) | ||
131 | #define SYSC_SIDLEMODE_MASK (0x3 << 3) | ||
132 | #define SYSC_ENAWAKEUP_MASK (1 << 2) | ||
133 | #define SYSC_SOFTRESET_MASK (1 << 1) | ||
134 | #define SYSC_AUTOIDLE_MASK (1 << 0) | ||
135 | |||
136 | #define SYSC_IDLEMODE_SMART 0x2 | ||
137 | #define SYSC_CLOCKACTIVITY_FCLK 0x2 | ||
128 | 138 | ||
129 | /* I2C System Configuration Register (OMAP_I2C_SYSC): */ | ||
130 | #define OMAP_I2C_SYSC_SRST (1 << 1) /* Soft Reset */ | ||
131 | 139 | ||
132 | struct omap_i2c_dev { | 140 | struct omap_i2c_dev { |
133 | struct device *dev; | 141 | struct device *dev; |
@@ -239,13 +247,13 @@ static int omap_i2c_init(struct omap_i2c_dev *dev) | |||
239 | unsigned long internal_clk = 0; | 247 | unsigned long internal_clk = 0; |
240 | 248 | ||
241 | if (dev->rev >= OMAP_I2C_REV_2) { | 249 | if (dev->rev >= OMAP_I2C_REV_2) { |
242 | omap_i2c_write_reg(dev, OMAP_I2C_SYSC_REG, OMAP_I2C_SYSC_SRST); | 250 | omap_i2c_write_reg(dev, OMAP_I2C_SYSC_REG, SYSC_SOFTRESET_MASK); |
243 | /* For some reason we need to set the EN bit before the | 251 | /* For some reason we need to set the EN bit before the |
244 | * reset done bit gets set. */ | 252 | * reset done bit gets set. */ |
245 | timeout = jiffies + OMAP_I2C_TIMEOUT; | 253 | timeout = jiffies + OMAP_I2C_TIMEOUT; |
246 | omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, OMAP_I2C_CON_EN); | 254 | omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, OMAP_I2C_CON_EN); |
247 | while (!(omap_i2c_read_reg(dev, OMAP_I2C_SYSS_REG) & | 255 | while (!(omap_i2c_read_reg(dev, OMAP_I2C_SYSS_REG) & |
248 | OMAP_I2C_SYSS_RDONE)) { | 256 | SYSS_RESETDONE_MASK)) { |
249 | if (time_after(jiffies, timeout)) { | 257 | if (time_after(jiffies, timeout)) { |
250 | dev_warn(dev->dev, "timeout waiting " | 258 | dev_warn(dev->dev, "timeout waiting " |
251 | "for controller reset\n"); | 259 | "for controller reset\n"); |
@@ -253,6 +261,26 @@ static int omap_i2c_init(struct omap_i2c_dev *dev) | |||
253 | } | 261 | } |
254 | msleep(1); | 262 | msleep(1); |
255 | } | 263 | } |
264 | |||
265 | /* SYSC register is cleared by the reset; rewrite it */ | ||
266 | if (dev->rev == OMAP_I2C_REV_ON_2430) { | ||
267 | |||
268 | omap_i2c_write_reg(dev, OMAP_I2C_SYSC_REG, | ||
269 | SYSC_AUTOIDLE_MASK); | ||
270 | |||
271 | } else if (dev->rev >= OMAP_I2C_REV_ON_3430) { | ||
272 | u32 v; | ||
273 | |||
274 | v = SYSC_AUTOIDLE_MASK; | ||
275 | v |= SYSC_ENAWAKEUP_MASK; | ||
276 | v |= (SYSC_IDLEMODE_SMART << | ||
277 | __ffs(SYSC_SIDLEMODE_MASK)); | ||
278 | v |= (SYSC_CLOCKACTIVITY_FCLK << | ||
279 | __ffs(SYSC_CLOCKACTIVITY_MASK)); | ||
280 | |||
281 | omap_i2c_write_reg(dev, OMAP_I2C_SYSC_REG, v); | ||
282 | |||
283 | } | ||
256 | } | 284 | } |
257 | omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0); | 285 | omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0); |
258 | 286 | ||