[RFC/PATCH 4/4] gpio: smscece: Add support for gpio IO expander feature

2012-08-21 Thread Sourav Poddar
smsc can be used as an gpio io expander device also. So adding
support for configuring smsc pins as a gpio.

Cc: Benoit Cousson b-cous...@ti.com
Cc: Felipe Balbi ba...@ti.com
Cc: Santosh Shilimkar santosh.shilim...@ti.com
Signed-off-by: Sourav Poddar sourav.pod...@ti.com
---
 drivers/gpio/Kconfig|7 +
 drivers/gpio/Makefile   |1 +
 drivers/gpio/gpio-smscece.c |  373 +++
 3 files changed, 381 insertions(+), 0 deletions(-)
 create mode 100644 drivers/gpio/gpio-smscece.c

diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index b16c8a7..e883929 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -444,6 +444,13 @@ config GPIO_ADP5588_IRQ
  Say yes here to enable the adp5588 to be used as an interrupt
  controller. It requires the driver to be built in the kernel.
 
+config GPIO_SMSCECE
+   tristate SMSCECE 1099 I2C GPIO expander
+   depends on I2C
+   help
+ This option enables support for 18 GPIOs found
+ on SMSC ECE 1099 GPIO Expanders.
+
 comment PCI GPIO expanders:
 
 config GPIO_CS5535
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 153cace..7c803c5 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -12,6 +12,7 @@ obj-$(CONFIG_GPIO_74X164) += gpio-74x164.o
 obj-$(CONFIG_GPIO_AB8500)  += gpio-ab8500.o
 obj-$(CONFIG_GPIO_ADP5520) += gpio-adp5520.o
 obj-$(CONFIG_GPIO_ADP5588) += gpio-adp5588.o
+obj-$(CONFIG_GPIO_SMSCECE)  += gpio-smscece.o
 obj-$(CONFIG_GPIO_AMD8111) += gpio-amd8111.o
 obj-$(CONFIG_GPIO_ARIZONA) += gpio-arizona.o
 obj-$(CONFIG_GPIO_BT8XX)   += gpio-bt8xx.o
diff --git a/drivers/gpio/gpio-smscece.c b/drivers/gpio/gpio-smscece.c
new file mode 100644
index 000..0cb0959
--- /dev/null
+++ b/drivers/gpio/gpio-smscece.c
@@ -0,0 +1,373 @@
+/*
+ * GPIO Chip driver for smsc
+ * SMSC I/O Expander and QWERTY Keypad Controller
+ *
+ * Copyright 2012 Texas Instruments Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#include linux/module.h
+#include linux/kernel.h
+#include linux/slab.h
+#include linux/init.h
+#include linux/i2c.h
+#include linux/gpio.h
+#include linux/interrupt.h
+#include linux/irqdomain.h
+#include linux/irq.h
+#include linux/mfd/smsc.h
+#include linux/err.h
+
+struct smsc_gpio {
+   struct device *dev;
+   struct smsc *smsc;
+   struct gpio_chip gpio_chip;
+   struct mutex lock;  /* protect cached dir, dat_out */
+   /* protect serialized access to the interrupt controller bus */
+   struct mutex irq_lock;
+   unsigned gpio_start;
+   int type;
+   int flags;
+   int irq;
+   int irq_base;
+   unsigned int gpio_base;
+   unsigned int dat_out[5];
+   unsigned int dir[5];
+   unsigned int int_lvl[5];
+   unsigned int int_en[5];
+   unsigned int irq_mask[5];
+   unsigned int irq_stat[5];
+};
+
+static int smsc_gpio_get_value(struct gpio_chip *chip, unsigned off)
+{
+   struct smsc_gpio *sg =
+   container_of(chip, struct smsc_gpio, gpio_chip);
+   unsigned int get;
+   return !!(smsc_read(sg-dev,
+   (SMSC_GPIO_DATA_IN_START + SMSC_BANK(off))  SMSC_BIT(off),
+   get));
+}
+
+static void smsc_gpio_set_value(struct gpio_chip *chip,
+   unsigned off, int val)
+{
+   unsigned bank, bit;
+   struct smsc_gpio *sg =
+   container_of(chip, struct smsc_gpio, gpio_chip);
+
+   bank = SMSC_BANK(off);
+   bit = SMSC_BIT(off);
+
+   mutex_lock(sg-lock);
+   if (val)
+   sg-dat_out[bank] |= bit;
+   else
+   sg-dat_out[bank] = ~bit;
+
+   smsc_write(sg-dev, SMSC_GPIO_DATA_OUT_START + bank,
+  sg-dat_out[bank]);
+   mutex_unlock(sg-lock);
+}
+
+static int smsc_gpio_direction_input(struct gpio_chip *chip, unsigned off)
+{
+   unsigned int reg;
+   struct smsc_gpio *sg =
+   container_of(chip, struct smsc_gpio, gpio_chip);
+   int reg_dir;
+
+   mutex_lock(sg-lock);
+   reg_dir = SMSC_CFG_START + off;
+   smsc_read(sg-dev, reg_dir, reg);
+   reg |= SMSC_GPIO_INPUT_LOW;
+   mutex_unlock(sg-lock);
+
+   return smsc_write(sg-dev, reg_dir, reg);
+}
+
+static int smsc_gpio_direction_output(struct gpio_chip *chip,
+unsigned off, int val)
+{
+   unsigned int reg;
+   struct smsc_gpio *sg =
+   container_of(chip, struct smsc_gpio, gpio_chip);
+   int reg_dir;
+
+   mutex_lock(sg-lock);
+   reg_dir = SMSC_CFG_START + off;
+   smsc_read(sg-dev, reg_dir, reg);
+   reg |= SMSC_GPIO_OUTPUT_PP;
+   mutex_unlock(sg-lock);
+
+   return smsc_write(sg-dev, reg_dir, reg);
+}
+
+static int smsc_gpio_to_irq(struct gpio_chip *chip, unsigned off)
+{
+   struct smsc_gpio *sg =
+   container_of(chip, struct smsc_gpio, gpio_chip);
+  

Re: [RFC/PATCH 4/4] gpio: smscece: Add support for gpio IO expander feature

2012-08-21 Thread Felipe Balbi
Hi,

On Tue, Aug 21, 2012 at 04:15:40PM +0530, Sourav Poddar wrote:
 smsc can be used as an gpio io expander device also. So adding
 support for configuring smsc pins as a gpio.
 
 Cc: Benoit Cousson b-cous...@ti.com
 Cc: Felipe Balbi ba...@ti.com
 Cc: Santosh Shilimkar santosh.shilim...@ti.com
 Signed-off-by: Sourav Poddar sourav.pod...@ti.com
 ---
  drivers/gpio/Kconfig|7 +
  drivers/gpio/Makefile   |1 +
  drivers/gpio/gpio-smscece.c |  373 
 +++
  3 files changed, 381 insertions(+), 0 deletions(-)
  create mode 100644 drivers/gpio/gpio-smscece.c
 
 diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
 index b16c8a7..e883929 100644
 --- a/drivers/gpio/Kconfig
 +++ b/drivers/gpio/Kconfig
 @@ -444,6 +444,13 @@ config GPIO_ADP5588_IRQ
 Say yes here to enable the adp5588 to be used as an interrupt
 controller. It requires the driver to be built in the kernel.
  
 +config GPIO_SMSCECE
 + tristate SMSCECE 1099 I2C GPIO expander
 + depends on I2C
 + help
 +   This option enables support for 18 GPIOs found
 +   on SMSC ECE 1099 GPIO Expanders.
 +
  comment PCI GPIO expanders:
  
  config GPIO_CS5535
 diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
 index 153cace..7c803c5 100644
 --- a/drivers/gpio/Makefile
 +++ b/drivers/gpio/Makefile
 @@ -12,6 +12,7 @@ obj-$(CONFIG_GPIO_74X164)   += gpio-74x164.o
  obj-$(CONFIG_GPIO_AB8500)+= gpio-ab8500.o
  obj-$(CONFIG_GPIO_ADP5520)   += gpio-adp5520.o
  obj-$(CONFIG_GPIO_ADP5588)   += gpio-adp5588.o
 +obj-$(CONFIG_GPIO_SMSCECE)  += gpio-smscece.o
  obj-$(CONFIG_GPIO_AMD8111)   += gpio-amd8111.o
  obj-$(CONFIG_GPIO_ARIZONA)   += gpio-arizona.o
  obj-$(CONFIG_GPIO_BT8XX) += gpio-bt8xx.o
 diff --git a/drivers/gpio/gpio-smscece.c b/drivers/gpio/gpio-smscece.c
 new file mode 100644
 index 000..0cb0959
 --- /dev/null
 +++ b/drivers/gpio/gpio-smscece.c
 @@ -0,0 +1,373 @@
 +/*
 + * GPIO Chip driver for smsc
 + * SMSC I/O Expander and QWERTY Keypad Controller
 + *
 + * Copyright 2012 Texas Instruments Inc.
 + *
 + * Licensed under the GPL-2 or later.
 + */
 +
 +#include linux/module.h
 +#include linux/kernel.h
 +#include linux/slab.h
 +#include linux/init.h
 +#include linux/i2c.h
 +#include linux/gpio.h
 +#include linux/interrupt.h
 +#include linux/irqdomain.h
 +#include linux/irq.h
 +#include linux/mfd/smsc.h
 +#include linux/err.h
 +
 +struct smsc_gpio {
 + struct device *dev;
 + struct smsc *smsc;
 + struct gpio_chip gpio_chip;
 + struct mutex lock;  /* protect cached dir, dat_out */
 + /* protect serialized access to the interrupt controller bus */
 + struct mutex irq_lock;
 + unsigned gpio_start;
 + int type;
 + int flags;
 + int irq;
 + int irq_base;
 + unsigned int gpio_base;
 + unsigned int dat_out[5];
 + unsigned int dir[5];
 + unsigned int int_lvl[5];
 + unsigned int int_en[5];
 + unsigned int irq_mask[5];
 + unsigned int irq_stat[5];
 +};
 +
 +static int smsc_gpio_get_value(struct gpio_chip *chip, unsigned off)
 +{
 + struct smsc_gpio *sg =
 + container_of(chip, struct smsc_gpio, gpio_chip);
 + unsigned int get;
 + return !!(smsc_read(sg-dev,
 + (SMSC_GPIO_DATA_IN_START + SMSC_BANK(off))  SMSC_BIT(off),
 + get));
 +}
 +
 +static void smsc_gpio_set_value(struct gpio_chip *chip,
 + unsigned off, int val)
 +{
 + unsigned bank, bit;
 + struct smsc_gpio *sg =
 + container_of(chip, struct smsc_gpio, gpio_chip);
 +
 + bank = SMSC_BANK(off);
 + bit = SMSC_BIT(off);
 +
 + mutex_lock(sg-lock);
 + if (val)
 + sg-dat_out[bank] |= bit;
 + else
 + sg-dat_out[bank] = ~bit;
 +
 + smsc_write(sg-dev, SMSC_GPIO_DATA_OUT_START + bank,
 +sg-dat_out[bank]);
 + mutex_unlock(sg-lock);
 +}
 +
 +static int smsc_gpio_direction_input(struct gpio_chip *chip, unsigned off)
 +{
 + unsigned int reg;
 + struct smsc_gpio *sg =
 + container_of(chip, struct smsc_gpio, gpio_chip);
 + int reg_dir;
 +
 + mutex_lock(sg-lock);
 + reg_dir = SMSC_CFG_START + off;
 + smsc_read(sg-dev, reg_dir, reg);
 + reg |= SMSC_GPIO_INPUT_LOW;
 + mutex_unlock(sg-lock);
 +
 + return smsc_write(sg-dev, reg_dir, reg);
 +}
 +
 +static int smsc_gpio_direction_output(struct gpio_chip *chip,
 +  unsigned off, int val)
 +{
 + unsigned int reg;
 + struct smsc_gpio *sg =
 + container_of(chip, struct smsc_gpio, gpio_chip);
 + int reg_dir;
 +
 + mutex_lock(sg-lock);
 + reg_dir = SMSC_CFG_START + off;
 + smsc_read(sg-dev, reg_dir, reg);
 + reg |= SMSC_GPIO_OUTPUT_PP;
 + mutex_unlock(sg-lock);
 +
 + return smsc_write(sg-dev, reg_dir, reg);
 +}
 +
 +static int smsc_gpio_to_irq(struct gpio_chip *chip, unsigned off)
 +{
 + struct 

Re: [RFC/PATCH 4/4] gpio: smscece: Add support for gpio IO expander feature

2012-08-21 Thread Poddar, Sourav
Hi,

On Tue, Aug 21, 2012 at 4:23 PM, Felipe Balbi ba...@ti.com wrote:
 Hi,

 On Tue, Aug 21, 2012 at 04:15:40PM +0530, Sourav Poddar wrote:
 smsc can be used as an gpio io expander device also. So adding
 support for configuring smsc pins as a gpio.

 Cc: Benoit Cousson b-cous...@ti.com
 Cc: Felipe Balbi ba...@ti.com
 Cc: Santosh Shilimkar santosh.shilim...@ti.com
 Signed-off-by: Sourav Poddar sourav.pod...@ti.com
 ---
  drivers/gpio/Kconfig|7 +
  drivers/gpio/Makefile   |1 +
  drivers/gpio/gpio-smscece.c |  373 
 +++
  3 files changed, 381 insertions(+), 0 deletions(-)
  create mode 100644 drivers/gpio/gpio-smscece.c

 diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
 index b16c8a7..e883929 100644
 --- a/drivers/gpio/Kconfig
 +++ b/drivers/gpio/Kconfig
 @@ -444,6 +444,13 @@ config GPIO_ADP5588_IRQ
 Say yes here to enable the adp5588 to be used as an interrupt
 controller. It requires the driver to be built in the kernel.

 +config GPIO_SMSCECE
 + tristate SMSCECE 1099 I2C GPIO expander
 + depends on I2C
 + help
 +   This option enables support for 18 GPIOs found
 +   on SMSC ECE 1099 GPIO Expanders.
 +
  comment PCI GPIO expanders:

  config GPIO_CS5535
 diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
 index 153cace..7c803c5 100644
 --- a/drivers/gpio/Makefile
 +++ b/drivers/gpio/Makefile
 @@ -12,6 +12,7 @@ obj-$(CONFIG_GPIO_74X164)   += gpio-74x164.o
  obj-$(CONFIG_GPIO_AB8500)+= gpio-ab8500.o
  obj-$(CONFIG_GPIO_ADP5520)   += gpio-adp5520.o
  obj-$(CONFIG_GPIO_ADP5588)   += gpio-adp5588.o
 +obj-$(CONFIG_GPIO_SMSCECE)  += gpio-smscece.o
  obj-$(CONFIG_GPIO_AMD8111)   += gpio-amd8111.o
  obj-$(CONFIG_GPIO_ARIZONA)   += gpio-arizona.o
  obj-$(CONFIG_GPIO_BT8XX) += gpio-bt8xx.o
 diff --git a/drivers/gpio/gpio-smscece.c b/drivers/gpio/gpio-smscece.c
 new file mode 100644
 index 000..0cb0959
 --- /dev/null
 +++ b/drivers/gpio/gpio-smscece.c
 @@ -0,0 +1,373 @@
 +/*
 + * GPIO Chip driver for smsc
 + * SMSC I/O Expander and QWERTY Keypad Controller
 + *
 + * Copyright 2012 Texas Instruments Inc.
 + *
 + * Licensed under the GPL-2 or later.
 + */
 +
 +#include linux/module.h
 +#include linux/kernel.h
 +#include linux/slab.h
 +#include linux/init.h
 +#include linux/i2c.h
 +#include linux/gpio.h
 +#include linux/interrupt.h
 +#include linux/irqdomain.h
 +#include linux/irq.h
 +#include linux/mfd/smsc.h
 +#include linux/err.h
 +
 +struct smsc_gpio {
 + struct device *dev;
 + struct smsc *smsc;
 + struct gpio_chip gpio_chip;
 + struct mutex lock;  /* protect cached dir, dat_out */
 + /* protect serialized access to the interrupt controller bus */
 + struct mutex irq_lock;
 + unsigned gpio_start;
 + int type;
 + int flags;
 + int irq;
 + int irq_base;
 + unsigned int gpio_base;
 + unsigned int dat_out[5];
 + unsigned int dir[5];
 + unsigned int int_lvl[5];
 + unsigned int int_en[5];
 + unsigned int irq_mask[5];
 + unsigned int irq_stat[5];
 +};
 +
 +static int smsc_gpio_get_value(struct gpio_chip *chip, unsigned off)
 +{
 + struct smsc_gpio *sg =
 + container_of(chip, struct smsc_gpio, gpio_chip);
 + unsigned int get;
 + return !!(smsc_read(sg-dev,
 + (SMSC_GPIO_DATA_IN_START + SMSC_BANK(off))  SMSC_BIT(off),
 + get));
 +}
 +
 +static void smsc_gpio_set_value(struct gpio_chip *chip,
 + unsigned off, int val)
 +{
 + unsigned bank, bit;
 + struct smsc_gpio *sg =
 + container_of(chip, struct smsc_gpio, gpio_chip);
 +
 + bank = SMSC_BANK(off);
 + bit = SMSC_BIT(off);
 +
 + mutex_lock(sg-lock);
 + if (val)
 + sg-dat_out[bank] |= bit;
 + else
 + sg-dat_out[bank] = ~bit;
 +
 + smsc_write(sg-dev, SMSC_GPIO_DATA_OUT_START + bank,
 +sg-dat_out[bank]);
 + mutex_unlock(sg-lock);
 +}
 +
 +static int smsc_gpio_direction_input(struct gpio_chip *chip, unsigned off)
 +{
 + unsigned int reg;
 + struct smsc_gpio *sg =
 + container_of(chip, struct smsc_gpio, gpio_chip);
 + int reg_dir;
 +
 + mutex_lock(sg-lock);
 + reg_dir = SMSC_CFG_START + off;
 + smsc_read(sg-dev, reg_dir, reg);
 + reg |= SMSC_GPIO_INPUT_LOW;
 + mutex_unlock(sg-lock);
 +
 + return smsc_write(sg-dev, reg_dir, reg);
 +}
 +
 +static int smsc_gpio_direction_output(struct gpio_chip *chip,
 +  unsigned off, int val)
 +{
 + unsigned int reg;
 + struct smsc_gpio *sg =
 + container_of(chip, struct smsc_gpio, gpio_chip);
 + int reg_dir;
 +
 + mutex_lock(sg-lock);
 + reg_dir = SMSC_CFG_START + off;
 + smsc_read(sg-dev, reg_dir, reg);
 + reg |= SMSC_GPIO_OUTPUT_PP;
 + mutex_unlock(sg-lock);
 +
 + return smsc_write(sg-dev, reg_dir, reg);
 +}
 +
 +static int 

Re: [RFC/PATCH 4/4] gpio: smscece: Add support for gpio IO expander feature

2012-08-21 Thread Felipe Balbi
Hi,

On Tue, Aug 21, 2012 at 05:17:37PM +0530, Poddar, Sourav wrote:
  + if (type  IRQ_TYPE_LEVEL_HIGH)
  + sg-int_lvl[bank] |= bit;
  + else if (type  IRQ_TYPE_LEVEL_LOW)
  + sg-int_lvl[bank] = ~bit;
  + else
  + return -EINVAL;
 
  this looks wrong. You could have a user who wants to trigger on both
  HIGH and LOW levels, no ?
 
 Yes, I think there can be a scenario where gpio_keys are attached
 to this driver and signals a key press at low and key release at
 high. ?
  Will figure out a way to add support to check for case where
 both High and low levels are used.

could probably be done on a separate patch, maybe... Just now I saw that
HIGH and LOW levels use the same bit.

-- 
balbi


signature.asc
Description: Digital signature


Re: [RFC/PATCH 4/4] gpio: smscece: Add support for gpio IO expander feature

2012-08-21 Thread Poddar, Sourav
Hi,

On Tue, Aug 21, 2012 at 5:30 PM, Felipe Balbi ba...@ti.com wrote:
 Hi,

 On Tue, Aug 21, 2012 at 05:17:37PM +0530, Poddar, Sourav wrote:
  + if (type  IRQ_TYPE_LEVEL_HIGH)
  + sg-int_lvl[bank] |= bit;
  + else if (type  IRQ_TYPE_LEVEL_LOW)
  + sg-int_lvl[bank] = ~bit;
  + else
  + return -EINVAL;
 
  this looks wrong. You could have a user who wants to trigger on both
  HIGH and LOW levels, no ?
 
 Yes, I think there can be a scenario where gpio_keys are attached
 to this driver and signals a key press at low and key release at
 high. ?
  Will figure out a way to add support to check for case where
 both High and low levels are used.

 could probably be done on a separate patch, maybe... Just now I saw that
 HIGH and LOW levels use the same bit.

If I am understanding correctly, if they both uses the same bit we cannot
use both for a particular user. ?
 --
 balbi
--
To unsubscribe from this list: send the line unsubscribe linux-omap in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [RFC/PATCH 4/4] gpio: smscece: Add support for gpio IO expander feature

2012-08-21 Thread Felipe Balbi
On Tue, Aug 21, 2012 at 05:50:28PM +0530, Poddar, Sourav wrote:
 Hi,
 
 On Tue, Aug 21, 2012 at 5:30 PM, Felipe Balbi ba...@ti.com wrote:
  Hi,
 
  On Tue, Aug 21, 2012 at 05:17:37PM +0530, Poddar, Sourav wrote:
   + if (type  IRQ_TYPE_LEVEL_HIGH)
   + sg-int_lvl[bank] |= bit;
   + else if (type  IRQ_TYPE_LEVEL_LOW)
   + sg-int_lvl[bank] = ~bit;
   + else
   + return -EINVAL;
  
   this looks wrong. You could have a user who wants to trigger on both
   HIGH and LOW levels, no ?
  
  Yes, I think there can be a scenario where gpio_keys are attached
  to this driver and signals a key press at low and key release at
  high. ?
   Will figure out a way to add support to check for case where
  both High and low levels are used.
 
  could probably be done on a separate patch, maybe... Just now I saw that
  HIGH and LOW levels use the same bit.
 
 If I am understanding correctly, if they both uses the same bit we cannot
 use both for a particular user. ?

we can, it's just a bit more complex. If a user request both LOW and
HIGH, then you start with HIGH, once it triggers, before calling the
nested IRQ handler, you need to change it LOW. When low triggers, before
calling the nested IRQ handler, you need to change it to HIGH again. And
so on. I'm just not sure if that's valid on linux IRQ subsystem.

Anyone ?

-- 
balbi


signature.asc
Description: Digital signature


Re: [RFC/PATCH 4/4] gpio: smscece: Add support for gpio IO expander feature

2012-08-21 Thread Mark Brown
On Tue, Aug 21, 2012 at 03:22:18PM +0300, Felipe Balbi wrote:
 On Tue, Aug 21, 2012 at 05:50:28PM +0530, Poddar, Sourav wrote:

  If I am understanding correctly, if they both uses the same bit we cannot
  use both for a particular user. ?

 we can, it's just a bit more complex. If a user request both LOW and
 HIGH, then you start with HIGH, once it triggers, before calling the
 nested IRQ handler, you need to change it LOW. When low triggers, before
 calling the nested IRQ handler, you need to change it to HIGH again. And
 so on. I'm just not sure if that's valid on linux IRQ subsystem.

The given example was for keypress - usually a system would use edge
triggered interrupts in combination with reading the GPIO state rather
than level triggered interrupts.
--
To unsubscribe from this list: send the line unsubscribe linux-omap in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html