aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/i2c/i2c-s3c2410.txt2
-rw-r--r--drivers/i2c/busses/i2c-s3c2410.c66
2 files changed, 58 insertions, 10 deletions
diff --git a/Documentation/devicetree/bindings/i2c/i2c-s3c2410.txt b/Documentation/devicetree/bindings/i2c/i2c-s3c2410.txt
index 296eb4536129..278de8e64bbf 100644
--- a/Documentation/devicetree/bindings/i2c/i2c-s3c2410.txt
+++ b/Documentation/devicetree/bindings/i2c/i2c-s3c2410.txt
@@ -10,6 +10,8 @@ Required properties:
10 inside HDMIPHY block found on several samsung SoCs 10 inside HDMIPHY block found on several samsung SoCs
11 (d) "samsung, exynos5440-i2c", for s3c2440-like i2c used 11 (d) "samsung, exynos5440-i2c", for s3c2440-like i2c used
12 on EXYNOS5440 which does not need GPIO configuration. 12 on EXYNOS5440 which does not need GPIO configuration.
13 (e) "samsung, exynos5-sata-phy-i2c", for s3c2440-like i2c used as
14 a host to SATA PHY controller on an internal bus.
13 - reg: physical base address of the controller and length of memory mapped 15 - reg: physical base address of the controller and length of memory mapped
14 region. 16 region.
15 - interrupts: interrupt number to the cpu. 17 - interrupts: interrupt number to the cpu.
diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c
index bf8fb94ebc5d..09f251d0716f 100644
--- a/drivers/i2c/busses/i2c-s3c2410.c
+++ b/drivers/i2c/busses/i2c-s3c2410.c
@@ -86,6 +86,7 @@
86#define QUIRK_S3C2440 (1 << 0) 86#define QUIRK_S3C2440 (1 << 0)
87#define QUIRK_HDMIPHY (1 << 1) 87#define QUIRK_HDMIPHY (1 << 1)
88#define QUIRK_NO_GPIO (1 << 2) 88#define QUIRK_NO_GPIO (1 << 2)
89#define QUIRK_POLL (1 << 3)
89 90
90/* Max time to wait for bus to become idle after a xfer (in us) */ 91/* Max time to wait for bus to become idle after a xfer (in us) */
91#define S3C2410_IDLE_TIMEOUT 5000 92#define S3C2410_IDLE_TIMEOUT 5000
@@ -142,6 +143,8 @@ static struct platform_device_id s3c24xx_driver_ids[] = {
142}; 143};
143MODULE_DEVICE_TABLE(platform, s3c24xx_driver_ids); 144MODULE_DEVICE_TABLE(platform, s3c24xx_driver_ids);
144 145
146static int i2c_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat);
147
145#ifdef CONFIG_OF 148#ifdef CONFIG_OF
146static const struct of_device_id s3c24xx_i2c_match[] = { 149static const struct of_device_id s3c24xx_i2c_match[] = {
147 { .compatible = "samsung,s3c2410-i2c", .data = (void *)0 }, 150 { .compatible = "samsung,s3c2410-i2c", .data = (void *)0 },
@@ -150,6 +153,8 @@ static const struct of_device_id s3c24xx_i2c_match[] = {
150 .data = (void *)(QUIRK_S3C2440 | QUIRK_HDMIPHY | QUIRK_NO_GPIO) }, 153 .data = (void *)(QUIRK_S3C2440 | QUIRK_HDMIPHY | QUIRK_NO_GPIO) },
151 { .compatible = "samsung,exynos5440-i2c", 154 { .compatible = "samsung,exynos5440-i2c",
152 .data = (void *)(QUIRK_S3C2440 | QUIRK_NO_GPIO) }, 155 .data = (void *)(QUIRK_S3C2440 | QUIRK_NO_GPIO) },
156 { .compatible = "samsung,exynos5-sata-phy-i2c",
157 .data = (void *)(QUIRK_S3C2440 | QUIRK_POLL | QUIRK_NO_GPIO) },
153 {}, 158 {},
154}; 159};
155MODULE_DEVICE_TABLE(of, s3c24xx_i2c_match); 160MODULE_DEVICE_TABLE(of, s3c24xx_i2c_match);
@@ -188,7 +193,8 @@ static inline void s3c24xx_i2c_master_complete(struct s3c24xx_i2c *i2c, int ret)
188 if (ret) 193 if (ret)
189 i2c->msg_idx = ret; 194 i2c->msg_idx = ret;
190 195
191 wake_up(&i2c->wait); 196 if (!(i2c->quirks & QUIRK_POLL))
197 wake_up(&i2c->wait);
192} 198}
193 199
194static inline void s3c24xx_i2c_disable_ack(struct s3c24xx_i2c *i2c) 200static inline void s3c24xx_i2c_disable_ack(struct s3c24xx_i2c *i2c)
@@ -225,6 +231,22 @@ static inline void s3c24xx_i2c_enable_irq(struct s3c24xx_i2c *i2c)
225 writel(tmp | S3C2410_IICCON_IRQEN, i2c->regs + S3C2410_IICCON); 231 writel(tmp | S3C2410_IICCON_IRQEN, i2c->regs + S3C2410_IICCON);
226} 232}
227 233
234static bool is_ack(struct s3c24xx_i2c *i2c)
235{
236 int tries;
237
238 for (tries = 50; tries; --tries) {
239 if (readl(i2c->regs + S3C2410_IICCON)
240 & S3C2410_IICCON_IRQPEND) {
241 if (!(readl(i2c->regs + S3C2410_IICSTAT)
242 & S3C2410_IICSTAT_LASTBIT))
243 return true;
244 }
245 usleep_range(1000, 2000);
246 }
247 dev_err(i2c->dev, "ack was not recieved\n");
248 return false;
249}
228 250
229/* s3c24xx_i2c_message_start 251/* s3c24xx_i2c_message_start
230 * 252 *
@@ -269,6 +291,16 @@ static void s3c24xx_i2c_message_start(struct s3c24xx_i2c *i2c,
269 291
270 stat |= S3C2410_IICSTAT_START; 292 stat |= S3C2410_IICSTAT_START;
271 writel(stat, i2c->regs + S3C2410_IICSTAT); 293 writel(stat, i2c->regs + S3C2410_IICSTAT);
294
295 if (i2c->quirks & QUIRK_POLL) {
296 while ((i2c->msg_num != 0) && is_ack(i2c)) {
297 i2c_s3c_irq_nextbyte(i2c, stat);
298 stat = readl(i2c->regs + S3C2410_IICSTAT);
299
300 if (stat & S3C2410_IICSTAT_ARBITR)
301 dev_err(i2c->dev, "deal with arbitration loss\n");
302 }
303 }
272} 304}
273 305
274static inline void s3c24xx_i2c_stop(struct s3c24xx_i2c *i2c, int ret) 306static inline void s3c24xx_i2c_stop(struct s3c24xx_i2c *i2c, int ret)
@@ -676,6 +708,15 @@ static int s3c24xx_i2c_doxfer(struct s3c24xx_i2c *i2c,
676 s3c24xx_i2c_enable_irq(i2c); 708 s3c24xx_i2c_enable_irq(i2c);
677 s3c24xx_i2c_message_start(i2c, msgs); 709 s3c24xx_i2c_message_start(i2c, msgs);
678 710
711 if (i2c->quirks & QUIRK_POLL) {
712 ret = i2c->msg_idx;
713
714 if (ret != num)
715 dev_dbg(i2c->dev, "incomplete xfer (%d)\n", ret);
716
717 goto out;
718 }
719
679 timeout = wait_event_timeout(i2c->wait, i2c->msg_num == 0, HZ * 5); 720 timeout = wait_event_timeout(i2c->wait, i2c->msg_num == 0, HZ * 5);
680 721
681 ret = i2c->msg_idx; 722 ret = i2c->msg_idx;
@@ -821,6 +862,9 @@ static int s3c24xx_i2c_clockrate(struct s3c24xx_i2c *i2c, unsigned int *got)
821 if (div1 == 512) 862 if (div1 == 512)
822 iiccon |= S3C2410_IICCON_TXDIV_512; 863 iiccon |= S3C2410_IICCON_TXDIV_512;
823 864
865 if (i2c->quirks & QUIRK_POLL)
866 iiccon |= S3C2410_IICCON_SCALE(2);
867
824 writel(iiccon, i2c->regs + S3C2410_IICCON); 868 writel(iiccon, i2c->regs + S3C2410_IICCON);
825 869
826 if (i2c->quirks & QUIRK_S3C2440) { 870 if (i2c->quirks & QUIRK_S3C2440) {
@@ -1118,18 +1162,20 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
1118 * ensure no current IRQs pending 1162 * ensure no current IRQs pending
1119 */ 1163 */
1120 1164
1121 i2c->irq = ret = platform_get_irq(pdev, 0); 1165 if (!(i2c->quirks & QUIRK_POLL)) {
1122 if (ret <= 0) { 1166 i2c->irq = ret = platform_get_irq(pdev, 0);
1123 dev_err(&pdev->dev, "cannot find IRQ\n"); 1167 if (ret <= 0) {
1124 return ret; 1168 dev_err(&pdev->dev, "cannot find IRQ\n");
1125 } 1169 return ret;
1170 }
1126 1171
1127 ret = devm_request_irq(&pdev->dev, i2c->irq, s3c24xx_i2c_irq, 0, 1172 ret = devm_request_irq(&pdev->dev, i2c->irq, s3c24xx_i2c_irq, 0,
1128 dev_name(&pdev->dev), i2c); 1173 dev_name(&pdev->dev), i2c);
1129 1174
1130 if (ret != 0) { 1175 if (ret != 0) {
1131 dev_err(&pdev->dev, "cannot claim IRQ %d\n", i2c->irq); 1176 dev_err(&pdev->dev, "cannot claim IRQ %d\n", i2c->irq);
1132 return ret; 1177 return ret;
1178 }
1133 } 1179 }
1134 1180
1135 ret = s3c24xx_i2c_register_cpufreq(i2c); 1181 ret = s3c24xx_i2c_register_cpufreq(i2c);