Re: [linux-yocto] [PATCH] gpio-pca953x: add "drive" property

2016-03-10 Thread Bruce Ashfield

On 2016-03-10 2:58 PM, Saul Wold wrote:

From: Jussi Laako 

Galileo gen 2 has support for setting GPIO modes. Expose these
properties through the GPIO sysfs interface. This approach is bit hacky,
since it changes the interface semantics.

The original patch was by Josef Ahmad  and
made on top of kernel 3.8.


merged, and I just sent the SRCREV update.

Bruce



Signed-off-by: Ismo Puustinen 
Signed-off-by: Jussi Laako 
Signed-off-by: Saul Wold 
---
  drivers/gpio/gpio-pca953x.c   | 57 +++
  drivers/gpio/gpiolib-sysfs.c  | 78 +++
  drivers/gpio/gpiolib.c| 18 ++
  drivers/gpio/gpiolib.h|  4 +++
  include/asm-generic/gpio.h|  5 +++
  include/linux/gpio.h  | 10 ++
  include/linux/gpio/consumer.h | 11 ++
  include/linux/gpio/driver.h   |  2 ++
  8 files changed, 178 insertions(+), 7 deletions(-)

diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c
index f23a4b4..f99706f 100644
--- a/drivers/gpio/gpio-pca953x.c
+++ b/drivers/gpio/gpio-pca953x.c
@@ -39,6 +39,9 @@
  #define PCA957X_MSK   6
  #define PCA957X_INTS  7

+#define PCA953X_PUPD_EN35
+#define PCA953X_PUPD_SEL   36
+
  #define PCA_GPIO_MASK 0x00FF
  #define PCA_INT   0x0100
  #define PCA953X_TYPE  0x1000
@@ -375,6 +378,43 @@ exit:
mutex_unlock(&chip->i2c_lock);
  }

+static int pca953x_gpio_set_drive(struct gpio_chip *gc,
+unsigned off, unsigned mode)
+{
+   struct pca953x_chip *chip;
+   int ret = 0;
+   int val;
+
+   chip = container_of(gc, struct pca953x_chip, gpio_chip);
+
+   if (chip->chip_type != PCA953X_TYPE)
+   return -EINVAL;
+
+   mutex_lock(&chip->i2c_lock);
+
+   switch (mode) {
+   case GPIOF_DRIVE_PULLUP:
+   ret = pca953x_write_single(chip, PCA953X_PUPD_EN, 1, off) ||
+   pca953x_write_single(chip, PCA953X_PUPD_SEL, 1, 
off);
+   break;
+   case GPIOF_DRIVE_PULLDOWN:
+   ret = pca953x_write_single(chip, PCA953X_PUPD_EN, 1, off) ||
+   pca953x_write_single(chip, PCA953X_PUPD_SEL, 0, 
off);
+   break;
+   case GPIOF_DRIVE_STRONG:
+   case GPIOF_DRIVE_HIZ:
+   ret = pca953x_read_single(chip, PCA953X_PUPD_EN, &val, off) ||
+   pca953x_write_single(chip, PCA953X_PUPD_EN, 0, 
off) ||
+   pca953x_write_single(chip, PCA953X_PUPD_SEL, 
val, off);
+   break;
+   default:
+   ret = -EINVAL;
+   }
+
+   mutex_unlock(&chip->i2c_lock);
+   return ret;
+}
+
  static void pca953x_setup_gpio(struct pca953x_chip *chip, int gpios)
  {
struct gpio_chip *gc;
@@ -393,6 +433,9 @@ static void pca953x_setup_gpio(struct pca953x_chip *chip, 
int gpios)
gc->dev = &chip->client->dev;
gc->owner = THIS_MODULE;
gc->names = chip->names;
+
+   if (chip->chip_type == PCA953X_TYPE)
+   gc->set_drive = pca953x_gpio_set_drive;
  }

  #ifdef CONFIG_GPIO_PCA953X_IRQ
@@ -552,7 +595,7 @@ static irqreturn_t pca953x_irq_handler(int irq, void *devid)
  }

  static int pca953x_irq_setup(struct pca953x_chip *chip,
-int irq_base)
+int irq_base)
  {
struct i2c_client *client = chip->client;
int ret, i, offset = 0;
@@ -595,10 +638,10 @@ static int pca953x_irq_setup(struct pca953x_chip *chip,
}

ret =  gpiochip_irqchip_add(&chip->gpio_chip,
-   &pca953x_irq_chip,
-   irq_base,
-   handle_simple_irq,
-   IRQ_TYPE_NONE);
+   &pca953x_irq_chip,
+   irq_base,
+   handle_simple_irq,
+   IRQ_TYPE_NONE);
if (ret) {
dev_err(&client->dev,
"could not connect irqchip to gpiochip\n");
@@ -615,7 +658,7 @@ static int pca953x_irq_setup(struct pca953x_chip *chip,

  #else /* CONFIG_GPIO_PCA953X_IRQ */
  static int pca953x_irq_setup(struct pca953x_chip *chip,
-int irq_base)
+int irq_base)
  {
struct i2c_client *client = chip->client;

@@ -636,7 +679,7 @@ static int device_pca953x_init(struct pca953x_chip *chip, 
u32 invert)
goto out;

ret = pca953x_read_regs(chip, PCA953X_DIRECTION,
-  chip->reg_direction);
+  chip->reg_direction);
if (ret)
goto out;

diff --git a/drivers/gpio/gpiolib

[linux-yocto] [PATCH] gpio-pca953x: add "drive" property

2016-03-10 Thread Saul Wold
From: Jussi Laako 

Galileo gen 2 has support for setting GPIO modes. Expose these
properties through the GPIO sysfs interface. This approach is bit hacky,
since it changes the interface semantics.

The original patch was by Josef Ahmad  and
made on top of kernel 3.8.

Signed-off-by: Ismo Puustinen 
Signed-off-by: Jussi Laako 
Signed-off-by: Saul Wold 
---
 drivers/gpio/gpio-pca953x.c   | 57 +++
 drivers/gpio/gpiolib-sysfs.c  | 78 +++
 drivers/gpio/gpiolib.c| 18 ++
 drivers/gpio/gpiolib.h|  4 +++
 include/asm-generic/gpio.h|  5 +++
 include/linux/gpio.h  | 10 ++
 include/linux/gpio/consumer.h | 11 ++
 include/linux/gpio/driver.h   |  2 ++
 8 files changed, 178 insertions(+), 7 deletions(-)

diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c
index f23a4b4..f99706f 100644
--- a/drivers/gpio/gpio-pca953x.c
+++ b/drivers/gpio/gpio-pca953x.c
@@ -39,6 +39,9 @@
 #define PCA957X_MSK6
 #define PCA957X_INTS   7
 
+#define PCA953X_PUPD_EN35
+#define PCA953X_PUPD_SEL   36
+
 #define PCA_GPIO_MASK  0x00FF
 #define PCA_INT0x0100
 #define PCA953X_TYPE   0x1000
@@ -375,6 +378,43 @@ exit:
mutex_unlock(&chip->i2c_lock);
 }
 
+static int pca953x_gpio_set_drive(struct gpio_chip *gc,
+unsigned off, unsigned mode)
+{
+   struct pca953x_chip *chip;
+   int ret = 0;
+   int val;
+
+   chip = container_of(gc, struct pca953x_chip, gpio_chip);
+
+   if (chip->chip_type != PCA953X_TYPE)
+   return -EINVAL;
+
+   mutex_lock(&chip->i2c_lock);
+
+   switch (mode) {
+   case GPIOF_DRIVE_PULLUP:
+   ret = pca953x_write_single(chip, PCA953X_PUPD_EN, 1, off) ||
+   pca953x_write_single(chip, PCA953X_PUPD_SEL, 1, 
off);
+   break;
+   case GPIOF_DRIVE_PULLDOWN:
+   ret = pca953x_write_single(chip, PCA953X_PUPD_EN, 1, off) ||
+   pca953x_write_single(chip, PCA953X_PUPD_SEL, 0, 
off);
+   break;
+   case GPIOF_DRIVE_STRONG:
+   case GPIOF_DRIVE_HIZ:
+   ret = pca953x_read_single(chip, PCA953X_PUPD_EN, &val, off) ||
+   pca953x_write_single(chip, PCA953X_PUPD_EN, 0, 
off) ||
+   pca953x_write_single(chip, PCA953X_PUPD_SEL, 
val, off);
+   break;
+   default:
+   ret = -EINVAL;
+   }
+
+   mutex_unlock(&chip->i2c_lock);
+   return ret;
+}
+
 static void pca953x_setup_gpio(struct pca953x_chip *chip, int gpios)
 {
struct gpio_chip *gc;
@@ -393,6 +433,9 @@ static void pca953x_setup_gpio(struct pca953x_chip *chip, 
int gpios)
gc->dev = &chip->client->dev;
gc->owner = THIS_MODULE;
gc->names = chip->names;
+
+   if (chip->chip_type == PCA953X_TYPE)
+   gc->set_drive = pca953x_gpio_set_drive;
 }
 
 #ifdef CONFIG_GPIO_PCA953X_IRQ
@@ -552,7 +595,7 @@ static irqreturn_t pca953x_irq_handler(int irq, void *devid)
 }
 
 static int pca953x_irq_setup(struct pca953x_chip *chip,
-int irq_base)
+int irq_base)
 {
struct i2c_client *client = chip->client;
int ret, i, offset = 0;
@@ -595,10 +638,10 @@ static int pca953x_irq_setup(struct pca953x_chip *chip,
}
 
ret =  gpiochip_irqchip_add(&chip->gpio_chip,
-   &pca953x_irq_chip,
-   irq_base,
-   handle_simple_irq,
-   IRQ_TYPE_NONE);
+   &pca953x_irq_chip,
+   irq_base,
+   handle_simple_irq,
+   IRQ_TYPE_NONE);
if (ret) {
dev_err(&client->dev,
"could not connect irqchip to gpiochip\n");
@@ -615,7 +658,7 @@ static int pca953x_irq_setup(struct pca953x_chip *chip,
 
 #else /* CONFIG_GPIO_PCA953X_IRQ */
 static int pca953x_irq_setup(struct pca953x_chip *chip,
-int irq_base)
+int irq_base)
 {
struct i2c_client *client = chip->client;
 
@@ -636,7 +679,7 @@ static int device_pca953x_init(struct pca953x_chip *chip, 
u32 invert)
goto out;
 
ret = pca953x_read_regs(chip, PCA953X_DIRECTION,
-  chip->reg_direction);
+  chip->reg_direction);
if (ret)
goto out;
 
diff --git a/drivers/gpio/gpiolib-sysfs.c b/drivers/gpio/gpiolib-sysfs.c
index b57ed8e..b60e477 100644
--- a/drivers/gpio/gpiolib-sysfs.c
++