[PATCH v2 4/6] DRIVERS:I2C: I2C driver polling mode support
Vasanth Ananthan
vasanthananthan at gmail.com
Fri Nov 23 03:53:22 EST 2012
Hi,
Missed to include Ben, for I2C patch, including him and copying others.
Thanks,
Vasanth.
On Tue, Oct 30, 2012 at 9:31 PM, Vasanth Ananthan
<vasanthananthan at gmail.com> wrote:
> This patch adds polling mode support for i2c s3c-2410 driver.
> The I2C_SATAPHY controller lacks an interrupt line but the s3c-2410 driver
> is interrupt driven. Hence this support is required for functioning
> of the I2C_SATAPHY controller.
>
> Signed-off-by: Vasanth Ananthan <vasanth.a at samsung.com>
> ---
> drivers/i2c/busses/i2c-s3c2410.c | 79 ++++++++++++++++++++++++++++---------
> 1 files changed, 60 insertions(+), 19 deletions(-)
>
> diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c
> index 3e0335f..5712e40 100644
> --- a/drivers/i2c/busses/i2c-s3c2410.c
> +++ b/drivers/i2c/busses/i2c-s3c2410.c
> @@ -48,6 +48,7 @@
> #define QUIRK_S3C2440 (1 << 0)
> #define QUIRK_HDMIPHY (1 << 1)
> #define QUIRK_NO_GPIO (1 << 2)
> +#define QUIRK_SATAPHY (1 << 3)
>
> /* i2c controller state */
> enum s3c24xx_i2c_state {
> @@ -102,10 +103,14 @@ static struct platform_device_id s3c24xx_driver_ids[] = {
> };
> MODULE_DEVICE_TABLE(platform, s3c24xx_driver_ids);
>
> +static int i2c_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat);
> +
> #ifdef CONFIG_OF
> static const struct of_device_id s3c24xx_i2c_match[] = {
> { .compatible = "samsung,s3c2410-i2c", .data = (void *)0 },
> { .compatible = "samsung,s3c2440-i2c", .data = (void *)QUIRK_S3C2440 },
> + { .compatible = "samsung,exynos5-sata-phy-i2c",
> + .data = (void *)(QUIRK_S3C2440 | QUIRK_SATAPHY | QUIRK_NO_GPIO) },
> { .compatible = "samsung,s3c2440-hdmiphy-i2c",
> .data = (void *)(QUIRK_S3C2440 | QUIRK_HDMIPHY | QUIRK_NO_GPIO) },
> {},
> @@ -146,7 +151,8 @@ static inline void s3c24xx_i2c_master_complete(struct s3c24xx_i2c *i2c, int ret)
> if (ret)
> i2c->msg_idx = ret;
>
> - wake_up(&i2c->wait);
> + if (!(i2c->quirks & QUIRK_SATAPHY))
> + wake_up(&i2c->wait);
> }
>
> static inline void s3c24xx_i2c_disable_ack(struct s3c24xx_i2c *i2c)
> @@ -184,6 +190,23 @@ static inline void s3c24xx_i2c_enable_irq(struct s3c24xx_i2c *i2c)
> }
>
>
> +static bool is_ack(struct s3c24xx_i2c *i2c)
> +{
> + u32 time_out = i2c->tx_setup;
> +
> + while (--time_out) {
> + if (readl(i2c->regs + S3C2410_IICCON)
> + & S3C2410_IICCON_IRQPEND) {
> + if (!(readl(i2c->regs + S3C2410_IICSTAT)
> + & S3C2410_IICSTAT_LASTBIT))
> + return true;
> + }
> + udelay(time_out);
> + }
> +
> + return false;
> +}
> +
> /* s3c24xx_i2c_message_start
> *
> * put the start of a message onto the bus
> @@ -227,6 +250,15 @@ static void s3c24xx_i2c_message_start(struct s3c24xx_i2c *i2c,
>
> stat |= S3C2410_IICSTAT_START;
> writel(stat, i2c->regs + S3C2410_IICSTAT);
> +
> + if (i2c->quirks & QUIRK_SATAPHY) {
> + while ((i2c->msg_num != 0) && is_ack(i2c)) {
> + i2c_s3c_irq_nextbyte(i2c, stat);
> + stat = readl(i2c->regs + S3C2410_IICSTAT);
> + if (stat & S3C2410_IICSTAT_ARBITR)
> + dev_err(i2c->dev, "deal with arbitration loss\n");
> + }
> + }
> }
>
> static inline void s3c24xx_i2c_stop(struct s3c24xx_i2c *i2c, int ret)
> @@ -552,19 +584,23 @@ static int s3c24xx_i2c_doxfer(struct s3c24xx_i2c *i2c,
> s3c24xx_i2c_message_start(i2c, msgs);
> spin_unlock_irq(&i2c->lock);
>
> - timeout = wait_event_timeout(i2c->wait, i2c->msg_num == 0, HZ * 5);
> -
> ret = i2c->msg_idx;
>
> - /* having these next two as dev_err() makes life very
> - * noisy when doing an i2cdetect */
> + if (!(i2c->quirks & QUIRK_SATAPHY)) {
>
> - if (timeout == 0)
> - dev_dbg(i2c->dev, "timeout\n");
> - else if (ret != num)
> - dev_dbg(i2c->dev, "incomplete xfer (%d)\n", ret);
> + timeout = wait_event_timeout(i2c->wait,
> + i2c->msg_num == 0, HZ * 5);
>
> - /* ensure the stop has been through the bus */
> + /* having these next two as dev_err() makes life very
> + * noisy when doing an i2cdetect */
> +
> + if (timeout == 0)
> + dev_dbg(i2c->dev, "timeout\n");
> + else if (ret != num)
> + dev_dbg(i2c->dev, "incomplete xfer (%d)\n", ret);
> +
> + /* ensure the stop has been through the bus */
> + }
>
> dev_dbg(i2c->dev, "waiting for bus idle\n");
>
> @@ -710,6 +746,9 @@ static int s3c24xx_i2c_clockrate(struct s3c24xx_i2c *i2c, unsigned int *got)
> if (div1 == 512)
> iiccon |= S3C2410_IICCON_TXDIV_512;
>
> + if (i2c->quirks & QUIRK_SATAPHY)
> + iiccon |= S3C2410_IICCON_SCALE(2);
> +
> writel(iiccon, i2c->regs + S3C2410_IICCON);
>
> if (i2c->quirks & QUIRK_S3C2440) {
> @@ -1023,18 +1062,20 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
> * ensure no current IRQs pending
> */
>
> - i2c->irq = ret = platform_get_irq(pdev, 0);
> - if (ret <= 0) {
> - dev_err(&pdev->dev, "cannot find IRQ\n");
> - goto err_iomap;
> - }
> + if (!(i2c->quirks & QUIRK_SATAPHY)) {
> + i2c->irq = ret = platform_get_irq(pdev, 0);
> + if (ret <= 0) {
> + dev_err(&pdev->dev, "cannot find IRQ\n");
> + goto err_iomap;
> + }
>
> - ret = request_irq(i2c->irq, s3c24xx_i2c_irq, 0,
> + ret = request_irq(i2c->irq, s3c24xx_i2c_irq, 0,
> dev_name(&pdev->dev), i2c);
>
> - if (ret != 0) {
> - dev_err(&pdev->dev, "cannot claim IRQ %d\n", i2c->irq);
> - goto err_iomap;
> + if (ret != 0) {
> + dev_err(&pdev->dev, "cannot claim IRQ %d\n", i2c->irq);
> + goto err_iomap;
> + }
> }
>
> ret = s3c24xx_i2c_register_cpufreq(i2c);
> --
> 1.7.4.1
>
--
Regards,
Vasanth K A
More information about the linux-arm-kernel
mailing list