aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/i2c
diff options
context:
space:
mode:
authorChristopher Kenna <cjk@cs.unc.edu>2012-09-28 13:46:28 -0400
committerChristopher Kenna <cjk@cs.unc.edu>2012-09-28 14:50:15 -0400
commitdaa22703f14c007e93b464c45fa60019a36f546d (patch)
treea1a130b6e128dc9d57c35c026977e1b4953105e1 /drivers/i2c
parent5aa287dcf1b5879aa0150b0511833c52885f5b4c (diff)
Apply k4412 kernel from HardKernel for ODROID-X.
Diffstat (limited to 'drivers/i2c')
-rw-r--r--drivers/i2c/busses/i2c-s3c2410.c103
1 files changed, 90 insertions, 13 deletions
diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c
index f84a63c6dd9..d7ae653cec0 100644
--- a/drivers/i2c/busses/i2c-s3c2410.c
+++ b/drivers/i2c/busses/i2c-s3c2410.c
@@ -54,6 +54,7 @@ enum s3c24xx_i2c_state {
54enum s3c24xx_i2c_type { 54enum s3c24xx_i2c_type {
55 TYPE_S3C2410, 55 TYPE_S3C2410,
56 TYPE_S3C2440, 56 TYPE_S3C2440,
57 TYPE_S3C2440_HDMIPHY,
57}; 58};
58 59
59struct s3c24xx_i2c { 60struct s3c24xx_i2c {
@@ -85,6 +86,17 @@ struct s3c24xx_i2c {
85 86
86/* default platform data removed, dev should always carry data. */ 87/* default platform data removed, dev should always carry data. */
87 88
89static inline void dump_i2c_register(struct s3c24xx_i2c *i2c)
90{
91 dev_dbg(i2c->dev, "Register dump(%d) : %x %x %x %x %x\n"
92 , i2c->suspended
93 , readl(i2c->regs + S3C2410_IICCON)
94 , readl(i2c->regs + S3C2410_IICSTAT)
95 , readl(i2c->regs + S3C2410_IICADD)
96 , readl(i2c->regs + S3C2410_IICDS)
97 , readl(i2c->regs + S3C2440_IICLC));
98}
99
88/* s3c24xx_i2c_is2440() 100/* s3c24xx_i2c_is2440()
89 * 101 *
90 * return true is this is an s3c2440 102 * return true is this is an s3c2440
@@ -96,7 +108,20 @@ static inline int s3c24xx_i2c_is2440(struct s3c24xx_i2c *i2c)
96 enum s3c24xx_i2c_type type; 108 enum s3c24xx_i2c_type type;
97 109
98 type = platform_get_device_id(pdev)->driver_data; 110 type = platform_get_device_id(pdev)->driver_data;
99 return type == TYPE_S3C2440; 111 return type == TYPE_S3C2440 || type == TYPE_S3C2440_HDMIPHY;
112}
113
114/* s3c24xx_i2c_is2440_hdmiphy()
115 *
116 * return true is this is an s3c2440 dedicated for HDMIPHY interface
117*/
118static inline int s3c24xx_i2c_is2440_hdmiphy(struct s3c24xx_i2c *i2c)
119{
120 struct platform_device *pdev = to_platform_device(i2c->dev);
121 enum s3c24xx_i2c_type type;
122
123 type = platform_get_device_id(pdev)->driver_data;
124 return type == TYPE_S3C2440_HDMIPHY;
100} 125}
101 126
102/* s3c24xx_i2c_master_complete 127/* s3c24xx_i2c_master_complete
@@ -201,18 +226,29 @@ static void s3c24xx_i2c_message_start(struct s3c24xx_i2c *i2c,
201 226
202static inline void s3c24xx_i2c_stop(struct s3c24xx_i2c *i2c, int ret) 227static inline void s3c24xx_i2c_stop(struct s3c24xx_i2c *i2c, int ret)
203{ 228{
204 unsigned long iicstat = readl(i2c->regs + S3C2410_IICSTAT); 229 unsigned long iicstat;
230 unsigned long iiccon;
205 231
206 dev_dbg(i2c->dev, "STOP\n"); 232 dev_dbg(i2c->dev, "STOP\n");
207 233
208 /* stop the transfer */ 234 /* stop the transfer */
235
236 /* Disable irq */
237 s3c24xx_i2c_disable_irq(i2c);
238
239 /* STOP signal generation : MTx(0xD0) */
240 iicstat = readl(i2c->regs + S3C2410_IICSTAT);
209 iicstat &= ~S3C2410_IICSTAT_START; 241 iicstat &= ~S3C2410_IICSTAT_START;
210 writel(iicstat, i2c->regs + S3C2410_IICSTAT); 242 writel(iicstat, i2c->regs + S3C2410_IICSTAT);
211 243
212 i2c->state = STATE_STOP; 244 /* Clear pending bit */
245 iiccon = readl(i2c->regs + S3C2410_IICCON);
246 iiccon &= ~S3C2410_IICCON_IRQPEND;
247 writel(iiccon, i2c->regs + S3C2410_IICCON);
213 248
214 s3c24xx_i2c_master_complete(i2c, ret); 249 s3c24xx_i2c_master_complete(i2c, ret);
215 s3c24xx_i2c_disable_irq(i2c); 250
251 i2c->state = STATE_STOP;
216} 252}
217 253
218/* helper functions to determine the current state in the set of 254/* helper functions to determine the current state in the set of
@@ -348,12 +384,21 @@ static int i2c_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat)
348 * forces us to send a new START 384 * forces us to send a new START
349 * when we change direction */ 385 * when we change direction */
350 386
387 dev_dbg(i2c->dev, "Cannot do this\n");
351 s3c24xx_i2c_stop(i2c, -EINVAL); 388 s3c24xx_i2c_stop(i2c, -EINVAL);
352 } 389 }
353 390
391 /* For multiple messages,
392 * ex)
393 * Msg[0]: Slave Addr + Write(Addr)
394 * Msg[1]: Write(Data) */
354 goto retry_write; 395 goto retry_write;
355 } else { 396 } else {
356 /* send the new start */ 397 /* send the new start */
398 /* For multiple messages,
399 * ex)
400 * Msg[0]: Slave Addr + Write(Addr)
401 * Msg[1]: Slave Addr + Read/Write(Data) */
357 s3c24xx_i2c_message_start(i2c, i2c->msg); 402 s3c24xx_i2c_message_start(i2c, i2c->msg);
358 i2c->state = STATE_START; 403 i2c->state = STATE_START;
359 } 404 }
@@ -424,6 +469,8 @@ static irqreturn_t s3c24xx_i2c_irq(int irqno, void *dev_id)
424 unsigned long status; 469 unsigned long status;
425 unsigned long tmp; 470 unsigned long tmp;
426 471
472 spin_lock(&i2c->lock);
473
427 status = readl(i2c->regs + S3C2410_IICSTAT); 474 status = readl(i2c->regs + S3C2410_IICSTAT);
428 475
429 if (status & S3C2410_IICSTAT_ARBITR) { 476 if (status & S3C2410_IICSTAT_ARBITR) {
@@ -446,6 +493,8 @@ static irqreturn_t s3c24xx_i2c_irq(int irqno, void *dev_id)
446 i2c_s3c_irq_nextbyte(i2c, status); 493 i2c_s3c_irq_nextbyte(i2c, status);
447 494
448 out: 495 out:
496 spin_unlock(&i2c->lock);
497
449 return IRQ_HANDLED; 498 return IRQ_HANDLED;
450} 499}
451 500
@@ -490,6 +539,7 @@ static int s3c24xx_i2c_doxfer(struct s3c24xx_i2c *i2c,
490 ret = s3c24xx_i2c_set_master(i2c); 539 ret = s3c24xx_i2c_set_master(i2c);
491 if (ret != 0) { 540 if (ret != 0) {
492 dev_err(i2c->dev, "cannot get bus (error %d)\n", ret); 541 dev_err(i2c->dev, "cannot get bus (error %d)\n", ret);
542 dump_i2c_register(i2c);
493 ret = -EAGAIN; 543 ret = -EAGAIN;
494 goto out; 544 goto out;
495 } 545 }
@@ -513,10 +563,13 @@ static int s3c24xx_i2c_doxfer(struct s3c24xx_i2c *i2c,
513 /* having these next two as dev_err() makes life very 563 /* having these next two as dev_err() makes life very
514 * noisy when doing an i2cdetect */ 564 * noisy when doing an i2cdetect */
515 565
516 if (timeout == 0) 566 if (timeout == 0) {
517 dev_dbg(i2c->dev, "timeout\n"); 567 dev_dbg(i2c->dev, "timeout\n");
518 else if (ret != num) 568 dump_i2c_register(i2c);
569 } else if (ret != num) {
519 dev_dbg(i2c->dev, "incomplete xfer (%d)\n", ret); 570 dev_dbg(i2c->dev, "incomplete xfer (%d)\n", ret);
571 dump_i2c_register(i2c);
572 }
520 573
521 /* ensure the stop has been through the bus */ 574 /* ensure the stop has been through the bus */
522 575
@@ -525,7 +578,7 @@ static int s3c24xx_i2c_doxfer(struct s3c24xx_i2c *i2c,
525 /* first, try busy waiting briefly */ 578 /* first, try busy waiting briefly */
526 do { 579 do {
527 iicstat = readl(i2c->regs + S3C2410_IICSTAT); 580 iicstat = readl(i2c->regs + S3C2410_IICSTAT);
528 } while ((iicstat & S3C2410_IICSTAT_START) && --spins); 581 } while ((iicstat & S3C2410_IICSTAT_BUSBUSY) && --spins);
529 582
530 /* if that timed out sleep */ 583 /* if that timed out sleep */
531 if (!spins) { 584 if (!spins) {
@@ -533,8 +586,23 @@ static int s3c24xx_i2c_doxfer(struct s3c24xx_i2c *i2c,
533 iicstat = readl(i2c->regs + S3C2410_IICSTAT); 586 iicstat = readl(i2c->regs + S3C2410_IICSTAT);
534 } 587 }
535 588
536 if (iicstat & S3C2410_IICSTAT_START) 589 /* if still not finished, clean it up */
537 dev_warn(i2c->dev, "timeout waiting for bus idle\n"); 590 spin_lock_irq(&i2c->lock);
591 if (iicstat & S3C2410_IICSTAT_BUSBUSY) {
592 dev_dbg(i2c->dev, "timeout waiting for bus idle\n");
593 dump_i2c_register(i2c);
594
595 if (i2c->state != STATE_STOP) {
596 dev_dbg(i2c->dev, "timeout : i2c interrupt hasn't occurred\n");
597 s3c24xx_i2c_stop(i2c, 0);
598 }
599
600 /* Disable Serial Out : To forcely terminate the connection */
601 iicstat = readl(i2c->regs + S3C2410_IICSTAT);
602 iicstat &= ~S3C2410_IICSTAT_TXRXEN;
603 writel(iicstat, i2c->regs + S3C2410_IICSTAT);
604 }
605 spin_unlock_irq(&i2c->lock);
538 606
539 out: 607 out:
540 return ret; 608 return ret;
@@ -553,6 +621,12 @@ static int s3c24xx_i2c_xfer(struct i2c_adapter *adap,
553 int retry; 621 int retry;
554 int ret; 622 int ret;
555 623
624 if (i2c->suspended) {
625 dev_err(i2c->dev, "I2C is not initialzed.\n");
626 dump_i2c_register(i2c);
627 return -EIO;
628 }
629
556 clk_enable(i2c->clk); 630 clk_enable(i2c->clk);
557 631
558 for (retry = 0; retry < adap->retries; retry++) { 632 for (retry = 0; retry < adap->retries; retry++) {
@@ -710,7 +784,7 @@ static int s3c24xx_i2c_cpufreq_transition(struct notifier_block *nb,
710 if (ret < 0) 784 if (ret < 0)
711 dev_err(i2c->dev, "cannot find frequency\n"); 785 dev_err(i2c->dev, "cannot find frequency\n");
712 else 786 else
713 dev_info(i2c->dev, "setting freq %d\n", got); 787 dev_dbg(i2c->dev, "setting freq %d\n", got);
714 } 788 }
715 789
716 return 0; 790 return 0;
@@ -765,7 +839,7 @@ static int s3c24xx_i2c_init(struct s3c24xx_i2c *i2c)
765 839
766 writeb(pdata->slave_addr, i2c->regs + S3C2410_IICADD); 840 writeb(pdata->slave_addr, i2c->regs + S3C2410_IICADD);
767 841
768 dev_info(i2c->dev, "slave address 0x%02x\n", pdata->slave_addr); 842 dev_dbg(i2c->dev, "slave address 0x%02x\n", pdata->slave_addr);
769 843
770 writel(iicon, i2c->regs + S3C2410_IICCON); 844 writel(iicon, i2c->regs + S3C2410_IICCON);
771 845
@@ -779,7 +853,7 @@ static int s3c24xx_i2c_init(struct s3c24xx_i2c *i2c)
779 853
780 /* todo - check that the i2c lines aren't being dragged anywhere */ 854 /* todo - check that the i2c lines aren't being dragged anywhere */
781 855
782 dev_info(i2c->dev, "bus frequency set to %d KHz\n", freq); 856 dev_dbg(i2c->dev, "bus frequency set to %d KHz\n", freq);
783 dev_dbg(i2c->dev, "S3C2410_IICCON=0x%02lx\n", iicon); 857 dev_dbg(i2c->dev, "S3C2410_IICCON=0x%02lx\n", iicon);
784 858
785 return 0; 859 return 0;
@@ -981,10 +1055,10 @@ static int s3c24xx_i2c_resume(struct device *dev)
981 struct platform_device *pdev = to_platform_device(dev); 1055 struct platform_device *pdev = to_platform_device(dev);
982 struct s3c24xx_i2c *i2c = platform_get_drvdata(pdev); 1056 struct s3c24xx_i2c *i2c = platform_get_drvdata(pdev);
983 1057
984 i2c->suspended = 0;
985 clk_enable(i2c->clk); 1058 clk_enable(i2c->clk);
986 s3c24xx_i2c_init(i2c); 1059 s3c24xx_i2c_init(i2c);
987 clk_disable(i2c->clk); 1060 clk_disable(i2c->clk);
1061 i2c->suspended = 0;
988 1062
989 return 0; 1063 return 0;
990} 1064}
@@ -1008,6 +1082,9 @@ static struct platform_device_id s3c24xx_driver_ids[] = {
1008 }, { 1082 }, {
1009 .name = "s3c2440-i2c", 1083 .name = "s3c2440-i2c",
1010 .driver_data = TYPE_S3C2440, 1084 .driver_data = TYPE_S3C2440,
1085 }, {
1086 .name = "s3c2440-hdmiphy-i2c",
1087 .driver_data = TYPE_S3C2440_HDMIPHY,
1011 }, { }, 1088 }, { },
1012}; 1089};
1013MODULE_DEVICE_TABLE(platform, s3c24xx_driver_ids); 1090MODULE_DEVICE_TABLE(platform, s3c24xx_driver_ids);