aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/i2c/busses/i2c-omap.c
diff options
context:
space:
mode:
authorAndrea Bastoni <bastoni@cs.unc.edu>2010-05-30 19:16:45 -0400
committerAndrea Bastoni <bastoni@cs.unc.edu>2010-05-30 19:16:45 -0400
commitada47b5fe13d89735805b566185f4885f5a3f750 (patch)
tree644b88f8a71896307d71438e9b3af49126ffb22b /drivers/i2c/busses/i2c-omap.c
parent43e98717ad40a4ae64545b5ba047c7b86aa44f4f (diff)
parent3280f21d43ee541f97f8cda5792150d2dbec20d5 (diff)
Merge branch 'wip-2.6.34' into old-private-masterarchived-private-master
Diffstat (limited to 'drivers/i2c/busses/i2c-omap.c')
-rw-r--r--drivers/i2c/busses/i2c-omap.c118
1 files changed, 77 insertions, 41 deletions
diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
index 827da0858136..389ac6032a7b 100644
--- a/drivers/i2c/busses/i2c-omap.c
+++ b/drivers/i2c/busses/i2c-omap.c
@@ -37,6 +37,7 @@
37#include <linux/platform_device.h> 37#include <linux/platform_device.h>
38#include <linux/clk.h> 38#include <linux/clk.h>
39#include <linux/io.h> 39#include <linux/io.h>
40#include <linux/slab.h>
40 41
41/* I2C controller revisions */ 42/* I2C controller revisions */
42#define OMAP_I2C_REV_2 0x20 43#define OMAP_I2C_REV_2 0x20
@@ -49,24 +50,24 @@
49#define OMAP_I2C_TIMEOUT (msecs_to_jiffies(1000)) 50#define OMAP_I2C_TIMEOUT (msecs_to_jiffies(1000))
50 51
51#define OMAP_I2C_REV_REG 0x00 52#define OMAP_I2C_REV_REG 0x00
52#define OMAP_I2C_IE_REG 0x04 53#define OMAP_I2C_IE_REG 0x01
53#define OMAP_I2C_STAT_REG 0x08 54#define OMAP_I2C_STAT_REG 0x02
54#define OMAP_I2C_IV_REG 0x0c 55#define OMAP_I2C_IV_REG 0x03
55/* For OMAP3 I2C_IV has changed to I2C_WE (wakeup enable) */ 56/* For OMAP3 I2C_IV has changed to I2C_WE (wakeup enable) */
56#define OMAP_I2C_WE_REG 0x0c 57#define OMAP_I2C_WE_REG 0x03
57#define OMAP_I2C_SYSS_REG 0x10 58#define OMAP_I2C_SYSS_REG 0x04
58#define OMAP_I2C_BUF_REG 0x14 59#define OMAP_I2C_BUF_REG 0x05
59#define OMAP_I2C_CNT_REG 0x18 60#define OMAP_I2C_CNT_REG 0x06
60#define OMAP_I2C_DATA_REG 0x1c 61#define OMAP_I2C_DATA_REG 0x07
61#define OMAP_I2C_SYSC_REG 0x20 62#define OMAP_I2C_SYSC_REG 0x08
62#define OMAP_I2C_CON_REG 0x24 63#define OMAP_I2C_CON_REG 0x09
63#define OMAP_I2C_OA_REG 0x28 64#define OMAP_I2C_OA_REG 0x0a
64#define OMAP_I2C_SA_REG 0x2c 65#define OMAP_I2C_SA_REG 0x0b
65#define OMAP_I2C_PSC_REG 0x30 66#define OMAP_I2C_PSC_REG 0x0c
66#define OMAP_I2C_SCLL_REG 0x34 67#define OMAP_I2C_SCLL_REG 0x0d
67#define OMAP_I2C_SCLH_REG 0x38 68#define OMAP_I2C_SCLH_REG 0x0e
68#define OMAP_I2C_SYSTEST_REG 0x3c 69#define OMAP_I2C_SYSTEST_REG 0x0f
69#define OMAP_I2C_BUFSTAT_REG 0x40 70#define OMAP_I2C_BUFSTAT_REG 0x10
70 71
71/* I2C Interrupt Enable Register (OMAP_I2C_IE): */ 72/* I2C Interrupt Enable Register (OMAP_I2C_IE): */
72#define OMAP_I2C_IE_XDR (1 << 14) /* TX Buffer drain int enable */ 73#define OMAP_I2C_IE_XDR (1 << 14) /* TX Buffer drain int enable */
@@ -161,6 +162,7 @@ struct omap_i2c_dev {
161 struct device *dev; 162 struct device *dev;
162 void __iomem *base; /* virtual */ 163 void __iomem *base; /* virtual */
163 int irq; 164 int irq;
165 int reg_shift; /* bit shift for I2C register addresses */
164 struct clk *iclk; /* Interface clock */ 166 struct clk *iclk; /* Interface clock */
165 struct clk *fclk; /* Functional clock */ 167 struct clk *fclk; /* Functional clock */
166 struct completion cmd_complete; 168 struct completion cmd_complete;
@@ -178,17 +180,23 @@ struct omap_i2c_dev {
178 unsigned b_hw:1; /* bad h/w fixes */ 180 unsigned b_hw:1; /* bad h/w fixes */
179 unsigned idle:1; 181 unsigned idle:1;
180 u16 iestate; /* Saved interrupt register */ 182 u16 iestate; /* Saved interrupt register */
183 u16 pscstate;
184 u16 scllstate;
185 u16 sclhstate;
186 u16 bufstate;
187 u16 syscstate;
188 u16 westate;
181}; 189};
182 190
183static inline void omap_i2c_write_reg(struct omap_i2c_dev *i2c_dev, 191static inline void omap_i2c_write_reg(struct omap_i2c_dev *i2c_dev,
184 int reg, u16 val) 192 int reg, u16 val)
185{ 193{
186 __raw_writew(val, i2c_dev->base + reg); 194 __raw_writew(val, i2c_dev->base + (reg << i2c_dev->reg_shift));
187} 195}
188 196
189static inline u16 omap_i2c_read_reg(struct omap_i2c_dev *i2c_dev, int reg) 197static inline u16 omap_i2c_read_reg(struct omap_i2c_dev *i2c_dev, int reg)
190{ 198{
191 return __raw_readw(i2c_dev->base + reg); 199 return __raw_readw(i2c_dev->base + (reg << i2c_dev->reg_shift));
192} 200}
193 201
194static int __init omap_i2c_get_clocks(struct omap_i2c_dev *dev) 202static int __init omap_i2c_get_clocks(struct omap_i2c_dev *dev)
@@ -230,7 +238,22 @@ static void omap_i2c_unidle(struct omap_i2c_dev *dev)
230 238
231 clk_enable(dev->iclk); 239 clk_enable(dev->iclk);
232 clk_enable(dev->fclk); 240 clk_enable(dev->fclk);
241 if (cpu_is_omap34xx()) {
242 omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0);
243 omap_i2c_write_reg(dev, OMAP_I2C_PSC_REG, dev->pscstate);
244 omap_i2c_write_reg(dev, OMAP_I2C_SCLL_REG, dev->scllstate);
245 omap_i2c_write_reg(dev, OMAP_I2C_SCLH_REG, dev->sclhstate);
246 omap_i2c_write_reg(dev, OMAP_I2C_BUF_REG, dev->bufstate);
247 omap_i2c_write_reg(dev, OMAP_I2C_SYSC_REG, dev->syscstate);
248 omap_i2c_write_reg(dev, OMAP_I2C_WE_REG, dev->westate);
249 omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, OMAP_I2C_CON_EN);
250 }
233 dev->idle = 0; 251 dev->idle = 0;
252
253 /*
254 * Don't write to this register if the IE state is 0 as it can
255 * cause deadlock.
256 */
234 if (dev->iestate) 257 if (dev->iestate)
235 omap_i2c_write_reg(dev, OMAP_I2C_IE_REG, dev->iestate); 258 omap_i2c_write_reg(dev, OMAP_I2C_IE_REG, dev->iestate);
236} 259}
@@ -258,13 +281,18 @@ static void omap_i2c_idle(struct omap_i2c_dev *dev)
258 281
259static int omap_i2c_init(struct omap_i2c_dev *dev) 282static int omap_i2c_init(struct omap_i2c_dev *dev)
260{ 283{
261 u16 psc = 0, scll = 0, sclh = 0; 284 u16 psc = 0, scll = 0, sclh = 0, buf = 0;
262 u16 fsscll = 0, fssclh = 0, hsscll = 0, hssclh = 0; 285 u16 fsscll = 0, fssclh = 0, hsscll = 0, hssclh = 0;
263 unsigned long fclk_rate = 12000000; 286 unsigned long fclk_rate = 12000000;
264 unsigned long timeout; 287 unsigned long timeout;
265 unsigned long internal_clk = 0; 288 unsigned long internal_clk = 0;
266 289
267 if (dev->rev >= OMAP_I2C_REV_2) { 290 if (dev->rev >= OMAP_I2C_REV_2) {
291 /* Disable I2C controller before soft reset */
292 omap_i2c_write_reg(dev, OMAP_I2C_CON_REG,
293 omap_i2c_read_reg(dev, OMAP_I2C_CON_REG) &
294 ~(OMAP_I2C_CON_EN));
295
268 omap_i2c_write_reg(dev, OMAP_I2C_SYSC_REG, SYSC_SOFTRESET_MASK); 296 omap_i2c_write_reg(dev, OMAP_I2C_SYSC_REG, SYSC_SOFTRESET_MASK);
269 /* For some reason we need to set the EN bit before the 297 /* For some reason we need to set the EN bit before the
270 * reset done bit gets set. */ 298 * reset done bit gets set. */
@@ -287,24 +315,22 @@ static int omap_i2c_init(struct omap_i2c_dev *dev)
287 SYSC_AUTOIDLE_MASK); 315 SYSC_AUTOIDLE_MASK);
288 316
289 } else if (dev->rev >= OMAP_I2C_REV_ON_3430) { 317 } else if (dev->rev >= OMAP_I2C_REV_ON_3430) {
290 u32 v; 318 dev->syscstate = SYSC_AUTOIDLE_MASK;
291 319 dev->syscstate |= SYSC_ENAWAKEUP_MASK;
292 v = SYSC_AUTOIDLE_MASK; 320 dev->syscstate |= (SYSC_IDLEMODE_SMART <<
293 v |= SYSC_ENAWAKEUP_MASK;
294 v |= (SYSC_IDLEMODE_SMART <<
295 __ffs(SYSC_SIDLEMODE_MASK)); 321 __ffs(SYSC_SIDLEMODE_MASK));
296 v |= (SYSC_CLOCKACTIVITY_FCLK << 322 dev->syscstate |= (SYSC_CLOCKACTIVITY_FCLK <<
297 __ffs(SYSC_CLOCKACTIVITY_MASK)); 323 __ffs(SYSC_CLOCKACTIVITY_MASK));
298 324
299 omap_i2c_write_reg(dev, OMAP_I2C_SYSC_REG, v); 325 omap_i2c_write_reg(dev, OMAP_I2C_SYSC_REG,
326 dev->syscstate);
300 /* 327 /*
301 * Enabling all wakup sources to stop I2C freezing on 328 * Enabling all wakup sources to stop I2C freezing on
302 * WFI instruction. 329 * WFI instruction.
303 * REVISIT: Some wkup sources might not be needed. 330 * REVISIT: Some wkup sources might not be needed.
304 */ 331 */
305 omap_i2c_write_reg(dev, OMAP_I2C_WE_REG, 332 dev->westate = OMAP_I2C_WE_ALL;
306 OMAP_I2C_WE_ALL); 333 omap_i2c_write_reg(dev, OMAP_I2C_WE_REG, dev->westate);
307
308 } 334 }
309 } 335 }
310 omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0); 336 omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0);
@@ -394,23 +420,28 @@ static int omap_i2c_init(struct omap_i2c_dev *dev)
394 omap_i2c_write_reg(dev, OMAP_I2C_SCLL_REG, scll); 420 omap_i2c_write_reg(dev, OMAP_I2C_SCLL_REG, scll);
395 omap_i2c_write_reg(dev, OMAP_I2C_SCLH_REG, sclh); 421 omap_i2c_write_reg(dev, OMAP_I2C_SCLH_REG, sclh);
396 422
397 if (dev->fifo_size) 423 if (dev->fifo_size) {
398 /* Note: setup required fifo size - 1 */ 424 /* Note: setup required fifo size - 1. RTRSH and XTRSH */
399 omap_i2c_write_reg(dev, OMAP_I2C_BUF_REG, 425 buf = (dev->fifo_size - 1) << 8 | OMAP_I2C_BUF_RXFIF_CLR |
400 (dev->fifo_size - 1) << 8 | /* RTRSH */ 426 (dev->fifo_size - 1) | OMAP_I2C_BUF_TXFIF_CLR;
401 OMAP_I2C_BUF_RXFIF_CLR | 427 omap_i2c_write_reg(dev, OMAP_I2C_BUF_REG, buf);
402 (dev->fifo_size - 1) | /* XTRSH */ 428 }
403 OMAP_I2C_BUF_TXFIF_CLR);
404 429
405 /* Take the I2C module out of reset: */ 430 /* Take the I2C module out of reset: */
406 omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, OMAP_I2C_CON_EN); 431 omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, OMAP_I2C_CON_EN);
407 432
408 /* Enable interrupts */ 433 /* Enable interrupts */
409 omap_i2c_write_reg(dev, OMAP_I2C_IE_REG, 434 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 | 435 OMAP_I2C_IE_ARDY | OMAP_I2C_IE_NACK |
412 OMAP_I2C_IE_AL) | ((dev->fifo_size) ? 436 OMAP_I2C_IE_AL) | ((dev->fifo_size) ?
413 (OMAP_I2C_IE_RDR | OMAP_I2C_IE_XDR) : 0)); 437 (OMAP_I2C_IE_RDR | OMAP_I2C_IE_XDR) : 0);
438 omap_i2c_write_reg(dev, OMAP_I2C_IE_REG, dev->iestate);
439 if (cpu_is_omap34xx()) {
440 dev->pscstate = psc;
441 dev->scllstate = scll;
442 dev->sclhstate = sclh;
443 dev->bufstate = buf;
444 }
414 return 0; 445 return 0;
415} 446}
416 447
@@ -820,7 +851,7 @@ static const struct i2c_algorithm omap_i2c_algo = {
820 .functionality = omap_i2c_func, 851 .functionality = omap_i2c_func,
821}; 852};
822 853
823static int __init 854static int __devinit
824omap_i2c_probe(struct platform_device *pdev) 855omap_i2c_probe(struct platform_device *pdev)
825{ 856{
826 struct omap_i2c_dev *dev; 857 struct omap_i2c_dev *dev;
@@ -872,6 +903,11 @@ omap_i2c_probe(struct platform_device *pdev)
872 903
873 platform_set_drvdata(pdev, dev); 904 platform_set_drvdata(pdev, dev);
874 905
906 if (cpu_is_omap7xx())
907 dev->reg_shift = 1;
908 else
909 dev->reg_shift = 2;
910
875 if ((r = omap_i2c_get_clocks(dev)) != 0) 911 if ((r = omap_i2c_get_clocks(dev)) != 0)
876 goto err_iounmap; 912 goto err_iounmap;
877 913