aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/i2c
diff options
context:
space:
mode:
authorKarol Lewandowski <k.lewandowsk@samsung.com>2012-04-23 12:24:01 -0400
committerWolfram Sang <w.sang@pengutronix.de>2012-05-12 08:28:16 -0400
commitec39ef83eb9b22cc732329e85fc4ec03e76d9dda (patch)
treefb6c6eabcc3b06db334d329080d04df78ff5fcf6 /drivers/i2c
parent27452498a6ed507154616d59e6bd41a96ec291c8 (diff)
i2c-s3c2410: Add HDMIPHY quirk for S3C2440
This patch adds support for s3c2440 I2C bus controller dedicated HDMIPHY device on Exynos4 platform. Some quirks are introduced due to differences between HDMIPHY and other I2C controllers on Exynos4. These differences are: - no GPIOs, HDMIPHY is inside the SoC and the controller is connected internally - due to unknown reason (probably HW bug in HDMIPHY and/or the controller) a transfer fails to finish. The controller hangs after sending the last byte, the workaround for this bug is resetting the controller after each transfer Signed-off-by: Tomasz Stanislawski <t.stanislaws@samsung.com> Signed-off-by: Karol Lewandowski <k.lewandowsk@samsung.com> Tested-by: Tomasz Stanislawski <t.stanislaws@samsung.com> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com> Signed-off-by: Wolfram Sang <w.sang@pengutronix.de>
Diffstat (limited to 'drivers/i2c')
-rw-r--r--drivers/i2c/busses/i2c-s3c2410.c30
1 files changed, 30 insertions, 0 deletions
diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c
index 23736ffaaa2a..fa0b13490873 100644
--- a/drivers/i2c/busses/i2c-s3c2410.c
+++ b/drivers/i2c/busses/i2c-s3c2410.c
@@ -46,6 +46,8 @@
46 46
47/* Treat S3C2410 as baseline hardware, anything else is supported via quirks */ 47/* Treat S3C2410 as baseline hardware, anything else is supported via quirks */
48#define QUIRK_S3C2440 (1 << 0) 48#define QUIRK_S3C2440 (1 << 0)
49#define QUIRK_HDMIPHY (1 << 1)
50#define QUIRK_NO_GPIO (1 << 2)
49 51
50/* i2c controller state */ 52/* i2c controller state */
51enum s3c24xx_i2c_state { 53enum s3c24xx_i2c_state {
@@ -93,6 +95,9 @@ static struct platform_device_id s3c24xx_driver_ids[] = {
93 }, { 95 }, {
94 .name = "s3c2440-i2c", 96 .name = "s3c2440-i2c",
95 .driver_data = QUIRK_S3C2440, 97 .driver_data = QUIRK_S3C2440,
98 }, {
99 .name = "s3c2440-hdmiphy-i2c",
100 .driver_data = QUIRK_S3C2440 | QUIRK_HDMIPHY | QUIRK_NO_GPIO,
96 }, { }, 101 }, { },
97}; 102};
98MODULE_DEVICE_TABLE(platform, s3c24xx_driver_ids); 103MODULE_DEVICE_TABLE(platform, s3c24xx_driver_ids);
@@ -101,6 +106,8 @@ MODULE_DEVICE_TABLE(platform, s3c24xx_driver_ids);
101static const struct of_device_id s3c24xx_i2c_match[] = { 106static const struct of_device_id s3c24xx_i2c_match[] = {
102 { .compatible = "samsung,s3c2410-i2c", .data = (void *)0 }, 107 { .compatible = "samsung,s3c2410-i2c", .data = (void *)0 },
103 { .compatible = "samsung,s3c2440-i2c", .data = (void *)QUIRK_S3C2440 }, 108 { .compatible = "samsung,s3c2440-i2c", .data = (void *)QUIRK_S3C2440 },
109 { .compatible = "samsung,s3c2440-hdmiphy-i2c",
110 .data = (void *)(QUIRK_S3C2440 | QUIRK_HDMIPHY | QUIRK_NO_GPIO) },
104 {}, 111 {},
105}; 112};
106MODULE_DEVICE_TABLE(of, s3c24xx_i2c_match); 113MODULE_DEVICE_TABLE(of, s3c24xx_i2c_match);
@@ -483,6 +490,13 @@ static int s3c24xx_i2c_set_master(struct s3c24xx_i2c *i2c)
483 unsigned long iicstat; 490 unsigned long iicstat;
484 int timeout = 400; 491 int timeout = 400;
485 492
493 /* the timeout for HDMIPHY is reduced to 10 ms because
494 * the hangup is expected to happen, so waiting 400 ms
495 * causes only unnecessary system hangup
496 */
497 if (i2c->quirks & QUIRK_HDMIPHY)
498 timeout = 10;
499
486 while (timeout-- > 0) { 500 while (timeout-- > 0) {
487 iicstat = readl(i2c->regs + S3C2410_IICSTAT); 501 iicstat = readl(i2c->regs + S3C2410_IICSTAT);
488 502
@@ -492,6 +506,15 @@ static int s3c24xx_i2c_set_master(struct s3c24xx_i2c *i2c)
492 msleep(1); 506 msleep(1);
493 } 507 }
494 508
509 /* hang-up of bus dedicated for HDMIPHY occurred, resetting */
510 if (i2c->quirks & QUIRK_HDMIPHY) {
511 writel(0, i2c->regs + S3C2410_IICCON);
512 writel(0, i2c->regs + S3C2410_IICSTAT);
513 writel(0, i2c->regs + S3C2410_IICDS);
514
515 return 0;
516 }
517
495 return -ETIMEDOUT; 518 return -ETIMEDOUT;
496} 519}
497 520
@@ -773,6 +796,9 @@ static int s3c24xx_i2c_parse_dt_gpio(struct s3c24xx_i2c *i2c)
773{ 796{
774 int idx, gpio, ret; 797 int idx, gpio, ret;
775 798
799 if (i2c->quirks & QUIRK_NO_GPIO)
800 return 0;
801
776 for (idx = 0; idx < 2; idx++) { 802 for (idx = 0; idx < 2; idx++) {
777 gpio = of_get_gpio(i2c->dev->of_node, idx); 803 gpio = of_get_gpio(i2c->dev->of_node, idx);
778 if (!gpio_is_valid(gpio)) { 804 if (!gpio_is_valid(gpio)) {
@@ -797,6 +823,10 @@ free_gpio:
797static void s3c24xx_i2c_dt_gpio_free(struct s3c24xx_i2c *i2c) 823static void s3c24xx_i2c_dt_gpio_free(struct s3c24xx_i2c *i2c)
798{ 824{
799 unsigned int idx; 825 unsigned int idx;
826
827 if (i2c->quirks & QUIRK_NO_GPIO)
828 return;
829
800 for (idx = 0; idx < 2; idx++) 830 for (idx = 0; idx < 2; idx++)
801 gpio_free(i2c->gpios[idx]); 831 gpio_free(i2c->gpios[idx]);
802} 832}