diff options
| -rw-r--r-- | Documentation/devicetree/bindings/i2c/samsung-i2c.txt | 8 | ||||
| -rw-r--r-- | drivers/i2c/busses/i2c-s3c2410.c | 30 |
2 files changed, 36 insertions, 2 deletions
diff --git a/Documentation/devicetree/bindings/i2c/samsung-i2c.txt b/Documentation/devicetree/bindings/i2c/samsung-i2c.txt index 38832c712919..b6cb5a12c672 100644 --- a/Documentation/devicetree/bindings/i2c/samsung-i2c.txt +++ b/Documentation/devicetree/bindings/i2c/samsung-i2c.txt | |||
| @@ -6,14 +6,18 @@ Required properties: | |||
| 6 | - compatible: value should be either of the following. | 6 | - compatible: value should be either of the following. |
| 7 | (a) "samsung, s3c2410-i2c", for i2c compatible with s3c2410 i2c. | 7 | (a) "samsung, s3c2410-i2c", for i2c compatible with s3c2410 i2c. |
| 8 | (b) "samsung, s3c2440-i2c", for i2c compatible with s3c2440 i2c. | 8 | (b) "samsung, s3c2440-i2c", for i2c compatible with s3c2440 i2c. |
| 9 | (c) "samsung, s3c2440-hdmiphy-i2c", for s3c2440-like i2c used | ||
| 10 | inside HDMIPHY block found on several samsung SoCs | ||
| 9 | - reg: physical base address of the controller and length of memory mapped | 11 | - reg: physical base address of the controller and length of memory mapped |
| 10 | region. | 12 | region. |
| 11 | - interrupts: interrupt number to the cpu. | 13 | - interrupts: interrupt number to the cpu. |
| 12 | - samsung,i2c-sda-delay: Delay (in ns) applied to data line (SDA) edges. | 14 | - samsung,i2c-sda-delay: Delay (in ns) applied to data line (SDA) edges. |
| 13 | - gpios: The order of the gpios should be the following: <SDA, SCL>. | ||
| 14 | The gpio specifier depends on the gpio controller. | ||
| 15 | 15 | ||
| 16 | Optional properties: | 16 | Optional properties: |
| 17 | - gpios: The order of the gpios should be the following: <SDA, SCL>. | ||
| 18 | The gpio specifier depends on the gpio controller. Required in all | ||
| 19 | cases except for "samsung,s3c2440-hdmiphy-i2c" whose input/output | ||
| 20 | lines are permanently wired to the respective client | ||
| 17 | - samsung,i2c-slave-addr: Slave address in multi-master enviroment. If not | 21 | - samsung,i2c-slave-addr: Slave address in multi-master enviroment. If not |
| 18 | specified, default value is 0. | 22 | specified, default value is 0. |
| 19 | - samsung,i2c-max-bus-freq: Desired frequency in Hz of the bus. If not | 23 | - samsung,i2c-max-bus-freq: Desired frequency in Hz of the bus. If not |
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 */ |
| 51 | enum s3c24xx_i2c_state { | 53 | enum 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 | }; |
| 98 | MODULE_DEVICE_TABLE(platform, s3c24xx_driver_ids); | 103 | MODULE_DEVICE_TABLE(platform, s3c24xx_driver_ids); |
| @@ -101,6 +106,8 @@ MODULE_DEVICE_TABLE(platform, s3c24xx_driver_ids); | |||
| 101 | static const struct of_device_id s3c24xx_i2c_match[] = { | 106 | static 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 | }; |
| 106 | MODULE_DEVICE_TABLE(of, s3c24xx_i2c_match); | 113 | MODULE_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: | |||
| 797 | static void s3c24xx_i2c_dt_gpio_free(struct s3c24xx_i2c *i2c) | 823 | static 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 | } |
