[RFC/PATCH 4/4] gpio: smscece: Add support for gpio IO expander feature
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
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
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
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
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
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
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