Re: [PATCH 05/12] i2c: pxa: Add bus reset functionality

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 





On Tuesday 02 June 2015 06:42 PM, Linus Walleij wrote:
On Thu, May 28, 2015 at 3:03 PM, Vaibhav Hiremath
<vaibhav.hiremath@xxxxxxxxxx> wrote:

From: Rob Herring <robh@xxxxxxxxxx>

Since there is some problematic i2c slave devices on some
platforms such as dkb (sometimes), it will drop down sda
and make i2c bus hang, at that time, it need to config
scl/sda into gpio to simulate "stop" sequence to recover
i2c bus, so add this interface.

Signed-off-by: Leilei Shang <shangll@xxxxxxxxxxx>
Signed-off-by: Rob Herring <robh@xxxxxxxxxx>
[vaibhav.hiremath@xxxxxxxxxx: Updated Changelog]
Signed-off-by: Vaibhav Hiremath <vaibhav.hiremath@xxxxxxxxxx>

Signed-off-by: Vaibhav Hiremath <vaibhav.hiremath@xxxxxxxxxx>

Double signed-off?

(...)
+#include <linux/of_gpio.h>

You should use <linux/gpio/consumer.h> and then use
GPIO descriptors instead.

@@ -177,6 +179,9 @@ struct pxa_i2c {
         bool                    highmode_enter;
         unsigned int            ilcr;
         unsigned int            iwcr;
+       struct pinctrl          *pinctrl;
+       struct pinctrl_state    *pin_i2c;
+       struct pinctrl_state    *pin_gpio;

Yup that's the right way. I see this is the "default"
state for pin_i2c.

+static void i2c_bus_reset(struct pxa_i2c *i2c)
+{
+       int ret, ccnt, pins_scl, pins_sda;

Use GPIO descriptors.

struct gpio_desc *scl, *sda;

+       struct device *dev = i2c->adap.dev.parent;
+       struct device_node *np = dev->of_node;
+
+       if (!i2c->pinctrl) {
+               dev_warn(dev, "could not do i2c bus reset\n");
+               return;
+       }
+
+       ret = pinctrl_select_state(i2c->pinctrl, i2c->pin_gpio);
+       if (ret) {
+               dev_err(dev, "could not set gpio pins\n");
+               return;
+       }

Exactly like that yes.

+       pins_scl = of_get_named_gpio(np, "i2c-gpio", 0);
+       if (!gpio_is_valid(pins_scl)) {
+               dev_err(dev, "i2c scl gpio not set\n");
+               goto err_out;
+       }
+       pins_sda = of_get_named_gpio(np, "i2c-gpio", 1);
+       if (!gpio_is_valid(pins_sda)) {
+               dev_err(dev, "i2c sda gpio not set\n");
+               goto err_out;
+       }

I would suggest just using two GPIOs in the node relying
on index order. With GPIO descriptors:

scl = gpiod_get_index(dev, "i2c-gpio", 0, GPIOD_ASIS);
sda = gpiod_get_index(dev, "i2c-gpio", 1, GPIOD_ASIS);

Then use gpiod* accessors below and...

+
+       gpio_request(pins_scl, NULL);
+       gpio_request(pins_sda, NULL);
+
+       gpio_direction_input(pins_sda);
+       for (ccnt = 20; ccnt; ccnt--) {
+               gpio_direction_output(pins_scl, ccnt & 0x01);
+               udelay(5);
+       }
+       gpio_direction_output(pins_scl, 0);
+       udelay(5);
+       gpio_direction_output(pins_sda, 0);
+       udelay(5);
+       /* stop signal */
+       gpio_direction_output(pins_scl, 1);
+       udelay(5);
+       gpio_direction_output(pins_sda, 1);
+       udelay(5);
+
+       gpio_free(pins_scl);
+       gpio_free(pins_sda);

gpiod_put(scl);
gpiod_put(sda);

+err_out:
+       ret = pinctrl_select_state(i2c->pinctrl, i2c->pin_i2c);
+       if (ret)
+               dev_err(dev, "could not set default(i2c) pins\n");
+       return;

Nice.

Overall it looks like a real nice structured workaround using
the API exactly as intended, just need to catch up with
using GPIO descriptors.



Thanks Linus,

I will work on this and submit V2 shortly.

Thanks,
Vaibhav

--
To unsubscribe from this list: send the line "unsubscribe linux-i2c" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux GPIO]     [Linux SPI]     [Linux Hardward Monitoring]     [LM Sensors]     [Linux USB Devel]     [Linux Media]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux