aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/i2c
diff options
context:
space:
mode:
authorVasanth Ananthan <vasanthananthan@gmail.com>2013-11-11 06:20:20 -0500
committerWolfram Sang <wsa@the-dreams.de>2014-01-03 11:40:36 -0500
commit117053f77a5a4d055ec4fc7b4f6639045a24fefd (patch)
treeb1554d85ca30f8b82caf8180d5afa1d2e47ef7c6 /drivers/i2c
parent46a4e737bc7ea3b07b0bc6f8315ab610a16c7eab (diff)
i2c: s3c2410: Add polling mode support
This patch adds polling mode support for i2c-s3c2410 driver.The SATA PHY controller's CMU and TRSV block's are of I2C register map in exynos5250.These blocks can be configured using i2c. But i2c controller instance on which these block's sits lacks an interrupt line.Also the current i2c-s3c2410 driver is only interrupt driven, thus a polling mode support is required in the driver for supporting this controller. This patch adds this support to the driver. Signed-off-by: Vasanth Ananthan <vasanth.a@samsung.com> Signed-off-by: Yuvaraj Kumar C D <yuvaraj.cd@samsung.com> Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
Diffstat (limited to 'drivers/i2c')
-rw-r--r--drivers/i2c/busses/i2c-s3c2410.c66
1 files changed, 56 insertions, 10 deletions
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);