From 5c470f39eea66ff00b31136f8bce9359d6b95375 Mon Sep 17 00:00:00 2001 From: John Bonesio Date: Wed, 22 Jun 2011 09:16:56 -0700 Subject: [PATCH 1/3] i2c: Tegra: Add DeviceTree support This patch modifies the tegra i2c driver so that it can be initiailized using the device tree along with the devices connected to the i2c bus. Signed-off-by: John Bonesio Acked-by: Grant Likely Acked-by: OIof Johansson Signed-off-by: Ben Dooks --- drivers/i2c/busses/i2c-tegra.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c index fb3b4f8f8152..2440b7411978 100644 --- a/drivers/i2c/busses/i2c-tegra.c +++ b/drivers/i2c/busses/i2c-tegra.c @@ -26,6 +26,7 @@ #include #include #include +#include #include @@ -546,6 +547,7 @@ static int tegra_i2c_probe(struct platform_device *pdev) struct resource *iomem; struct clk *clk; struct clk *i2c_clk; + const unsigned int *prop; void *base; int irq; int ret = 0; @@ -603,7 +605,17 @@ static int tegra_i2c_probe(struct platform_device *pdev) i2c_dev->irq = irq; i2c_dev->cont_id = pdev->id; i2c_dev->dev = &pdev->dev; - i2c_dev->bus_clk_rate = pdata ? pdata->bus_clk_rate : 100000; + + i2c_dev->bus_clk_rate = 100000; /* default clock rate */ + if (pdata) { + i2c_dev->bus_clk_rate = pdata->bus_clk_rate; + + } else if (i2c_dev->dev->of_node) { /* if there is a device tree node ... */ + prop = of_get_property(i2c_dev->dev->of_node, + "clock-frequency", NULL); + if (prop) + i2c_dev->bus_clk_rate = be32_to_cpup(prop); + } if (pdev->id == 3) i2c_dev->is_dvc = 1; @@ -633,6 +645,7 @@ static int tegra_i2c_probe(struct platform_device *pdev) i2c_dev->adapter.algo = &tegra_i2c_algo; i2c_dev->adapter.dev.parent = &pdev->dev; i2c_dev->adapter.nr = pdev->id; + i2c_dev->adapter.dev.of_node = pdev->dev.of_node; ret = i2c_add_numbered_adapter(&i2c_dev->adapter); if (ret) { @@ -640,6 +653,8 @@ static int tegra_i2c_probe(struct platform_device *pdev) goto err_free_irq; } + of_i2c_register_devices(&i2c_dev->adapter); + return 0; err_free_irq: free_irq(i2c_dev->irq, i2c_dev); From 7a9c42ccc9fd4317383e55209f825f974e64aa99 Mon Sep 17 00:00:00 2001 From: Tomoya MORINAGA Date: Thu, 9 Jun 2011 11:29:29 +0900 Subject: [PATCH 2/3] i2c-eg20t : Support Combined R/W transfer mode Currently, Combined R/W transfer mode is not supported. This patch enables Combined R/W transfer mode. Signed-off-by: Tomoya MORINAGA Signed-off-by: Ben Dooks --- drivers/i2c/busses/i2c-eg20t.c | 39 +++++++++++++++++----------------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/drivers/i2c/busses/i2c-eg20t.c b/drivers/i2c/busses/i2c-eg20t.c index 8abfa4a03ce1..9b072fd42108 100644 --- a/drivers/i2c/busses/i2c-eg20t.c +++ b/drivers/i2c/busses/i2c-eg20t.c @@ -673,25 +673,26 @@ static s32 pch_i2c_xfer(struct i2c_adapter *i2c_adap, /* transfer not completed */ adap->pch_i2c_xfer_in_progress = true; - pmsg = &msgs[0]; - pmsg->flags |= adap->pch_buff_mode_en; - status = pmsg->flags; - pch_dbg(adap, - "After invoking I2C_MODE_SEL :flag= 0x%x\n", status); - /* calculate sub address length and message length */ - /* these are applicable only for buffer mode */ - subaddrlen = pmsg->buf[0]; - /* calculate actual message length excluding - * the sub address fields */ - msglen = (pmsg->len) - (subaddrlen + 1); - if (status & (I2C_M_RD)) { - pch_dbg(adap, "invoking pch_i2c_readbytes\n"); - ret = pch_i2c_readbytes(i2c_adap, pmsg, (i + 1 == num), - (i == 0)); - } else { - pch_dbg(adap, "invoking pch_i2c_writebytes\n"); - ret = pch_i2c_writebytes(i2c_adap, pmsg, (i + 1 == num), - (i == 0)); + for (i = 0; i < num; i++) { + pmsg = &msgs[i]; + pmsg->flags |= adap->pch_buff_mode_en; + status = pmsg->flags; + pch_dbg(adap, + "After invoking I2C_MODE_SEL :flag= 0x%x\n", status); + /* calculate sub address length and message length */ + /* these are applicable only for buffer mode */ + subaddrlen = pmsg->buf[0]; + /* calculate actual message length excluding + * the sub address fields */ + msglen = (pmsg->len) - (subaddrlen + 1); + + if ((status & (I2C_M_RD)) != false) { + ret = pch_i2c_readbytes(i2c_adap, pmsg, (i + 1 == num), + (i == 0)); + } else { + ret = pch_i2c_writebytes(i2c_adap, pmsg, (i + 1 == num), + (i == 0)); + } } adap->pch_i2c_xfer_in_progress = false; /* transfer completed */ From 07e729ce894487e92405d3b221cffe587420a376 Mon Sep 17 00:00:00 2001 From: Tomoya MORINAGA Date: Thu, 23 Jun 2011 16:17:10 +0900 Subject: [PATCH 3/3] i2c-eg20t : Fix the issue of Combined R/W transfer mode issue-1 In case combined transfer mode fails halfway, the processing must be stopped halfway. However currently, the processing is continued. This patch breaks the processing. issue-2 Currently, pch_i2c_xfer returns read/write size at that time. However pch_i2c_xfer must return the number of messages to be read/written. This patch modifies correctly. Signed-off-by: Tomoya MORINAGA Signed-off-by: Ben Dooks --- drivers/i2c/busses/i2c-eg20t.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/i2c/busses/i2c-eg20t.c b/drivers/i2c/busses/i2c-eg20t.c index 9b072fd42108..ce1a32b71e47 100644 --- a/drivers/i2c/busses/i2c-eg20t.c +++ b/drivers/i2c/busses/i2c-eg20t.c @@ -673,7 +673,7 @@ static s32 pch_i2c_xfer(struct i2c_adapter *i2c_adap, /* transfer not completed */ adap->pch_i2c_xfer_in_progress = true; - for (i = 0; i < num; i++) { + for (i = 0; i < num && ret >= 0; i++) { pmsg = &msgs[i]; pmsg->flags |= adap->pch_buff_mode_en; status = pmsg->flags; @@ -699,7 +699,7 @@ static s32 pch_i2c_xfer(struct i2c_adapter *i2c_adap, mutex_unlock(&pch_mutex); - return ret; + return (ret < 0) ? ret : num; } /**