gpio: sx150x: Add Semtech I2C sx150x gpio expander driver.
Subsystems (3)
PATCH v3 1/1 gpio: sx150x: Add Semtech I2C sx150x gpio expander driver.
Add support for Semtech SX150-series I2C GPIO expanders. Compatible models include:
8 bits: sx1508q
16 bits: sx1509q
--- drivers/gpio/Kconfig | 11 + drivers/gpio/Makefile | 1 + drivers/gpio/sx150x.c | 646 ++++++++++++++++++++++++++++++++++++++++++++ include/linux/i2c/sx150x.h | 78 ++++++ 4 files changed, 736 insertions(+), 0 deletions(-) create mode 100644 drivers/gpio/sx150x.c create mode 100644 include/linux/i2c/sx150x.h
drivers/gpio/Kconfig +11 -0
@@ -195,6 +195,17 @@ config GPIO_PCF857X This driver provides an in-kernel interface to those GPIOs using platform-neutral GPIO calls. +config GPIO_SX150X + bool "Semtech SX150x I2C GPIO expander" + depends on I2C=y + default n + help + Say yes here to provide support for Semtech SX150-series I2C + GPIO expanders. Compatible models include: + + 8 bits: sx1508q + 16 bits: sx1509q + config GPIO_TC35892 bool "TC35892 GPIOs" depends on MFD_TC35892
drivers/gpio/Makefile +1 -0
@@ -35,3 +35,4 @@ obj-$(CONFIG_GPIO_WM8994) += wm8994-gpio.o obj-$(CONFIG_GPIO_SCH) += sch_gpio.o obj-$(CONFIG_GPIO_RDC321X) += rdc321x-gpio.o obj-$(CONFIG_GPIO_JANZ_TTL) += janz-ttl.o +obj-$(CONFIG_GPIO_SX150X) += sx150x.o
drivers/gpio/sx150x.c new file +646 -0
646 lines not on this page · raw message
include/linux/i2c/sx150x.h new file +78 -0
78 lines not on this page · raw message
Signature · 5 lines
1.7.0.4 -- Employee of Qualcomm Innovation Center, Inc. Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
On Tue, 20 Jul 2010 14:07:43 -0700
Gregory Bean <[email protected]> wrote:
Gregory,
Quoted 24 lines
Add support for Semtech SX150-series I2C GPIO expanders. Compatible models include:
8 bits: sx1508q
16 bits: sx1509qSigned-off-by Gregory Bean <[email protected]>drivers/gpio/sx150x.c new file +16
-0+static int sx150x_irq_set_type (unsigned int irq,unsigned int flow_type) +{ +struct irq_chip *ic =get_irq_chip (irq); +struct sx150x_chip *chip; +unsigned n, val =0 ; + +if (flow_type & (IRQ_TYPE_LEVEL_HIGH |IRQ_TYPE_LEVEL_LOW )) +return -EINVAL ; + + chip = container_of(ic, struct sx150x_chip, irq_chip); + n = irq - chip->irq_base; + +if (flow_type &IRQ_TYPE_EDGE_RISING ) + val |=0x1 ; +if (flow_type &IRQ_TYPE_EDGE_FALLING ) + val |=0x2 ;
drivers/gpio/sx150x.c line 364
Quoted 10 lines
drivers/gpio/sx150x.c new file +10
-0+ +mutex_lock (&chip->mutex); + chip->irq_sense &= ~(3UL << (n *2 )); + chip->irq_sense |= val << (n *2 ); +if (!(irq_to_desc (irq)->status &IRQ_MASKED )) +sx150x_write_cfg (chip, n,2 , chip->dev_cfg->reg_sense, val); +mutex_unlock (&chip->mutex); + +return 0 ; +}
Several problems here:
* This can be called from request_threaded irq(), which means the mutex is already taken (via the bus_lock method).
* On the same path, __setup_irq will disable local interrupts before calling this function. Bad things will happen if your I2C controller wants to sleep. pca953x had the same problem, see a2cb9aeb3c9b2475955cec328487484034f414e4 for a potential solution.
drivers/gpio/sx150x.c line 376
Quoted 11 lines
drivers/gpio/sx150x.c new file +11
-0+static irqreturn_t sx150x_irq_thread_fn (int irq,void *dev_id) +{ +struct sx150x_chip *chip = (struct sx150x_chip *)dev_id; +unsigned nhandled =0 ; +unsigned sub_irq; +unsigned n; +s32 err; +u8 val; +int i; + +mutex_lock (&chip->mutex);
This looks wrong... The whole purpose of the genirq framework is that it takes care of most of the locking for you if you provide the bus_lock/unlock methods. You should only use direct locking to protect against races from the gpiolib framework.
Quoted 13 lines
drivers/gpio/sx150x.c new file +13
-0+for (i = (chip->dev_cfg->ngpios /8 ) -1 ; i >=0 ; --i) { + err =sx150x_i2c_read (chip->client, + chip->dev_cfg->reg_irq_src - i, + &val); +if (err <0 ) +continue ; + +sx150x_i2c_write (chip->client, + chip->dev_cfg->reg_irq_src - i, + val); +for (n =0 ; n <8 ; ++n) { +if (val & (1 << n)) { + sub_irq = chip->irq_base + (i *8 ) + n;
drivers/gpio/sx150x.c line 399
Quoted 10 lines
drivers/gpio/sx150x.c new file +10
-0+handle_nested_irq (sub_irq); + ++nhandled; + } + } + } +mutex_unlock (&chip->mutex); + +return (nhandled >0 ?IRQ_HANDLED :IRQ_NONE ); +} +
Cheers,
M.
Signature · 4 lines
Enforcement officers may use a hand-held detection device to measure both the direction and the strength of a TV signal. This makes it easy for us to locate TV receiving equipment in even the hardest-to-reach places.