diff options
| -rw-r--r-- | drivers/i2c/busses/i2c-omap.c | 64 |
1 files changed, 41 insertions, 23 deletions
diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index 827da0858136..75bf3ad18099 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c | |||
| @@ -178,6 +178,12 @@ struct omap_i2c_dev { | |||
| 178 | unsigned b_hw:1; /* bad h/w fixes */ | 178 | unsigned b_hw:1; /* bad h/w fixes */ |
| 179 | unsigned idle:1; | 179 | unsigned idle:1; |
| 180 | u16 iestate; /* Saved interrupt register */ | 180 | u16 iestate; /* Saved interrupt register */ |
| 181 | u16 pscstate; | ||
| 182 | u16 scllstate; | ||
| 183 | u16 sclhstate; | ||
| 184 | u16 bufstate; | ||
| 185 | u16 syscstate; | ||
| 186 | u16 westate; | ||
| 181 | }; | 187 | }; |
| 182 | 188 | ||
| 183 | static inline void omap_i2c_write_reg(struct omap_i2c_dev *i2c_dev, | 189 | static inline void omap_i2c_write_reg(struct omap_i2c_dev *i2c_dev, |
| @@ -230,9 +236,18 @@ static void omap_i2c_unidle(struct omap_i2c_dev *dev) | |||
| 230 | 236 | ||
| 231 | clk_enable(dev->iclk); | 237 | clk_enable(dev->iclk); |
| 232 | clk_enable(dev->fclk); | 238 | clk_enable(dev->fclk); |
| 239 | if (cpu_is_omap34xx()) { | ||
| 240 | omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0); | ||
| 241 | omap_i2c_write_reg(dev, OMAP_I2C_PSC_REG, dev->pscstate); | ||
| 242 | omap_i2c_write_reg(dev, OMAP_I2C_SCLL_REG, dev->scllstate); | ||
| 243 | omap_i2c_write_reg(dev, OMAP_I2C_SCLH_REG, dev->sclhstate); | ||
| 244 | omap_i2c_write_reg(dev, OMAP_I2C_BUF_REG, dev->bufstate); | ||
| 245 | omap_i2c_write_reg(dev, OMAP_I2C_SYSC_REG, dev->syscstate); | ||
| 246 | omap_i2c_write_reg(dev, OMAP_I2C_WE_REG, dev->westate); | ||
| 247 | omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, OMAP_I2C_CON_EN); | ||
| 248 | } | ||
| 233 | dev->idle = 0; | 249 | dev->idle = 0; |
| 234 | if (dev->iestate) | 250 | omap_i2c_write_reg(dev, OMAP_I2C_IE_REG, dev->iestate); |
| 235 | omap_i2c_write_reg(dev, OMAP_I2C_IE_REG, dev->iestate); | ||
| 236 | } | 251 | } |
| 237 | 252 | ||
| 238 | static void omap_i2c_idle(struct omap_i2c_dev *dev) | 253 | static void omap_i2c_idle(struct omap_i2c_dev *dev) |
| @@ -258,7 +273,7 @@ static void omap_i2c_idle(struct omap_i2c_dev *dev) | |||
| 258 | 273 | ||
| 259 | static int omap_i2c_init(struct omap_i2c_dev *dev) | 274 | static int omap_i2c_init(struct omap_i2c_dev *dev) |
| 260 | { | 275 | { |
| 261 | u16 psc = 0, scll = 0, sclh = 0; | 276 | u16 psc = 0, scll = 0, sclh = 0, buf = 0; |
| 262 | u16 fsscll = 0, fssclh = 0, hsscll = 0, hssclh = 0; | 277 | u16 fsscll = 0, fssclh = 0, hsscll = 0, hssclh = 0; |
| 263 | unsigned long fclk_rate = 12000000; | 278 | unsigned long fclk_rate = 12000000; |
| 264 | unsigned long timeout; | 279 | unsigned long timeout; |
| @@ -287,24 +302,22 @@ static int omap_i2c_init(struct omap_i2c_dev *dev) | |||
| 287 | SYSC_AUTOIDLE_MASK); | 302 | SYSC_AUTOIDLE_MASK); |
| 288 | 303 | ||
| 289 | } else if (dev->rev >= OMAP_I2C_REV_ON_3430) { | 304 | } else if (dev->rev >= OMAP_I2C_REV_ON_3430) { |
| 290 | u32 v; | 305 | dev->syscstate = SYSC_AUTOIDLE_MASK; |
| 291 | 306 | dev->syscstate |= SYSC_ENAWAKEUP_MASK; | |
| 292 | v = SYSC_AUTOIDLE_MASK; | 307 | dev->syscstate |= (SYSC_IDLEMODE_SMART << |
| 293 | v |= SYSC_ENAWAKEUP_MASK; | ||
| 294 | v |= (SYSC_IDLEMODE_SMART << | ||
| 295 | __ffs(SYSC_SIDLEMODE_MASK)); | 308 | __ffs(SYSC_SIDLEMODE_MASK)); |
| 296 | v |= (SYSC_CLOCKACTIVITY_FCLK << | 309 | dev->syscstate |= (SYSC_CLOCKACTIVITY_FCLK << |
| 297 | __ffs(SYSC_CLOCKACTIVITY_MASK)); | 310 | __ffs(SYSC_CLOCKACTIVITY_MASK)); |
| 298 | 311 | ||
| 299 | omap_i2c_write_reg(dev, OMAP_I2C_SYSC_REG, v); | 312 | omap_i2c_write_reg(dev, OMAP_I2C_SYSC_REG, |
| 313 | dev->syscstate); | ||
| 300 | /* | 314 | /* |
| 301 | * Enabling all wakup sources to stop I2C freezing on | 315 | * Enabling all wakup sources to stop I2C freezing on |
| 302 | * WFI instruction. | 316 | * WFI instruction. |
| 303 | * REVISIT: Some wkup sources might not be needed. | 317 | * REVISIT: Some wkup sources might not be needed. |
| 304 | */ | 318 | */ |
| 305 | omap_i2c_write_reg(dev, OMAP_I2C_WE_REG, | 319 | dev->westate = OMAP_I2C_WE_ALL; |
| 306 | OMAP_I2C_WE_ALL); | 320 | omap_i2c_write_reg(dev, OMAP_I2C_WE_REG, dev->westate); |
| 307 | |||
| 308 | } | 321 | } |
| 309 | } | 322 | } |
| 310 | omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0); | 323 | omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0); |
| @@ -394,23 +407,28 @@ static int omap_i2c_init(struct omap_i2c_dev *dev) | |||
| 394 | omap_i2c_write_reg(dev, OMAP_I2C_SCLL_REG, scll); | 407 | omap_i2c_write_reg(dev, OMAP_I2C_SCLL_REG, scll); |
| 395 | omap_i2c_write_reg(dev, OMAP_I2C_SCLH_REG, sclh); | 408 | omap_i2c_write_reg(dev, OMAP_I2C_SCLH_REG, sclh); |
| 396 | 409 | ||
| 397 | if (dev->fifo_size) | 410 | if (dev->fifo_size) { |
| 398 | /* Note: setup required fifo size - 1 */ | 411 | /* Note: setup required fifo size - 1. RTRSH and XTRSH */ |
| 399 | omap_i2c_write_reg(dev, OMAP_I2C_BUF_REG, | 412 | buf = (dev->fifo_size - 1) << 8 | OMAP_I2C_BUF_RXFIF_CLR | |
| 400 | (dev->fifo_size - 1) << 8 | /* RTRSH */ | 413 | (dev->fifo_size - 1) | OMAP_I2C_BUF_TXFIF_CLR; |
| 401 | OMAP_I2C_BUF_RXFIF_CLR | | 414 | omap_i2c_write_reg(dev, OMAP_I2C_BUF_REG, buf); |
| 402 | (dev->fifo_size - 1) | /* XTRSH */ | 415 | } |
| 403 | OMAP_I2C_BUF_TXFIF_CLR); | ||
| 404 | 416 | ||
| 405 | /* Take the I2C module out of reset: */ | 417 | /* Take the I2C module out of reset: */ |
| 406 | omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, OMAP_I2C_CON_EN); | 418 | omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, OMAP_I2C_CON_EN); |
| 407 | 419 | ||
| 408 | /* Enable interrupts */ | 420 | /* Enable interrupts */ |
| 409 | omap_i2c_write_reg(dev, OMAP_I2C_IE_REG, | 421 | dev->iestate = (OMAP_I2C_IE_XRDY | OMAP_I2C_IE_RRDY | |
| 410 | (OMAP_I2C_IE_XRDY | OMAP_I2C_IE_RRDY | | ||
| 411 | OMAP_I2C_IE_ARDY | OMAP_I2C_IE_NACK | | 422 | OMAP_I2C_IE_ARDY | OMAP_I2C_IE_NACK | |
| 412 | OMAP_I2C_IE_AL) | ((dev->fifo_size) ? | 423 | OMAP_I2C_IE_AL) | ((dev->fifo_size) ? |
| 413 | (OMAP_I2C_IE_RDR | OMAP_I2C_IE_XDR) : 0)); | 424 | (OMAP_I2C_IE_RDR | OMAP_I2C_IE_XDR) : 0); |
| 425 | omap_i2c_write_reg(dev, OMAP_I2C_IE_REG, dev->iestate); | ||
| 426 | if (cpu_is_omap34xx()) { | ||
| 427 | dev->pscstate = psc; | ||
| 428 | dev->scllstate = scll; | ||
| 429 | dev->sclhstate = sclh; | ||
| 430 | dev->bufstate = buf; | ||
| 431 | } | ||
| 414 | return 0; | 432 | return 0; |
| 415 | } | 433 | } |
| 416 | 434 | ||
