103f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent/* 203f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent * Copyright (C) ST-Ericsson SA 2010 303f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent * 403f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent * License Terms: GNU General Public License, version 2 503f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson 603f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent */ 703f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent 803f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent#include <linux/module.h> 903f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent#include <linux/init.h> 1003f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent#include <linux/platform_device.h> 1103f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent#include <linux/slab.h> 1203f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent#include <linux/gpio.h> 1303f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent#include <linux/irq.h> 1403f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent#include <linux/interrupt.h> 1503f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent#include <linux/mfd/stmpe.h> 1603f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent 1703f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent/* 1803f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent * These registers are modified under the irq bus lock and cached to avoid 1903f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent * unnecessary writes in bus_sync_unlock. 2003f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent */ 2103f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincentenum { REG_RE, REG_FE, REG_IE }; 2203f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent 2303f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent#define CACHE_NR_REGS 3 2403f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent#define CACHE_NR_BANKS (STMPE_NR_GPIOS / 8) 2503f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent 2603f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincentstruct stmpe_gpio { 2703f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent struct gpio_chip chip; 2803f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent struct stmpe *stmpe; 2903f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent struct device *dev; 3003f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent struct mutex irq_lock; 3103f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent 3203f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent int irq_base; 33b8e9cf0b28173fc25dae9f3ac44de6fc4e9fc385Wolfram Sang unsigned norequest_mask; 3403f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent 3503f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent /* Caches of interrupt control registers for bus_lock */ 3603f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent u8 regs[CACHE_NR_REGS][CACHE_NR_BANKS]; 3703f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent u8 oldregs[CACHE_NR_REGS][CACHE_NR_BANKS]; 3803f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent}; 3903f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent 4003f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincentstatic inline struct stmpe_gpio *to_stmpe_gpio(struct gpio_chip *chip) 4103f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent{ 4203f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent return container_of(chip, struct stmpe_gpio, chip); 4303f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent} 4403f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent 4503f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincentstatic int stmpe_gpio_get(struct gpio_chip *chip, unsigned offset) 4603f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent{ 4703f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent struct stmpe_gpio *stmpe_gpio = to_stmpe_gpio(chip); 4803f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent struct stmpe *stmpe = stmpe_gpio->stmpe; 4903f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent u8 reg = stmpe->regs[STMPE_IDX_GPMR_LSB] - (offset / 8); 5003f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent u8 mask = 1 << (offset % 8); 5103f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent int ret; 5203f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent 5303f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent ret = stmpe_reg_read(stmpe, reg); 5403f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent if (ret < 0) 5503f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent return ret; 5603f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent 5703f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent return ret & mask; 5803f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent} 5903f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent 6003f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincentstatic void stmpe_gpio_set(struct gpio_chip *chip, unsigned offset, int val) 6103f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent{ 6203f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent struct stmpe_gpio *stmpe_gpio = to_stmpe_gpio(chip); 6303f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent struct stmpe *stmpe = stmpe_gpio->stmpe; 6403f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent int which = val ? STMPE_IDX_GPSR_LSB : STMPE_IDX_GPCR_LSB; 6503f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent u8 reg = stmpe->regs[which] - (offset / 8); 6603f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent u8 mask = 1 << (offset % 8); 6703f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent 68cccdceb938b37a415c42a0635b8a19893a3a19bbViresh Kumar /* 69cccdceb938b37a415c42a0635b8a19893a3a19bbViresh Kumar * Some variants have single register for gpio set/clear functionality. 70cccdceb938b37a415c42a0635b8a19893a3a19bbViresh Kumar * For them we need to write 0 to clear and 1 to set. 71cccdceb938b37a415c42a0635b8a19893a3a19bbViresh Kumar */ 72cccdceb938b37a415c42a0635b8a19893a3a19bbViresh Kumar if (stmpe->regs[STMPE_IDX_GPSR_LSB] == stmpe->regs[STMPE_IDX_GPCR_LSB]) 73cccdceb938b37a415c42a0635b8a19893a3a19bbViresh Kumar stmpe_set_bits(stmpe, reg, mask, val ? mask : 0); 74cccdceb938b37a415c42a0635b8a19893a3a19bbViresh Kumar else 75cccdceb938b37a415c42a0635b8a19893a3a19bbViresh Kumar stmpe_reg_write(stmpe, reg, mask); 7603f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent} 7703f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent 7803f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincentstatic int stmpe_gpio_direction_output(struct gpio_chip *chip, 7903f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent unsigned offset, int val) 8003f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent{ 8103f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent struct stmpe_gpio *stmpe_gpio = to_stmpe_gpio(chip); 8203f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent struct stmpe *stmpe = stmpe_gpio->stmpe; 8303f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent u8 reg = stmpe->regs[STMPE_IDX_GPDR_LSB] - (offset / 8); 8403f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent u8 mask = 1 << (offset % 8); 8503f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent 8603f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent stmpe_gpio_set(chip, offset, val); 8703f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent 8803f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent return stmpe_set_bits(stmpe, reg, mask, mask); 8903f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent} 9003f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent 9103f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincentstatic int stmpe_gpio_direction_input(struct gpio_chip *chip, 9203f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent unsigned offset) 9303f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent{ 9403f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent struct stmpe_gpio *stmpe_gpio = to_stmpe_gpio(chip); 9503f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent struct stmpe *stmpe = stmpe_gpio->stmpe; 9603f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent u8 reg = stmpe->regs[STMPE_IDX_GPDR_LSB] - (offset / 8); 9703f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent u8 mask = 1 << (offset % 8); 9803f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent 9903f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent return stmpe_set_bits(stmpe, reg, mask, 0); 10003f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent} 10103f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent 10203f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincentstatic int stmpe_gpio_to_irq(struct gpio_chip *chip, unsigned offset) 10303f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent{ 10403f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent struct stmpe_gpio *stmpe_gpio = to_stmpe_gpio(chip); 10503f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent 10603f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent return stmpe_gpio->irq_base + offset; 10703f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent} 10803f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent 10903f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincentstatic int stmpe_gpio_request(struct gpio_chip *chip, unsigned offset) 11003f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent{ 11103f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent struct stmpe_gpio *stmpe_gpio = to_stmpe_gpio(chip); 11203f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent struct stmpe *stmpe = stmpe_gpio->stmpe; 11303f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent 114b8e9cf0b28173fc25dae9f3ac44de6fc4e9fc385Wolfram Sang if (stmpe_gpio->norequest_mask & (1 << offset)) 115b8e9cf0b28173fc25dae9f3ac44de6fc4e9fc385Wolfram Sang return -EINVAL; 116b8e9cf0b28173fc25dae9f3ac44de6fc4e9fc385Wolfram Sang 11703f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent return stmpe_set_altfunc(stmpe, 1 << offset, STMPE_BLOCK_GPIO); 11803f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent} 11903f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent 12003f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincentstatic struct gpio_chip template_chip = { 12103f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent .label = "stmpe", 12203f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent .owner = THIS_MODULE, 12303f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent .direction_input = stmpe_gpio_direction_input, 12403f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent .get = stmpe_gpio_get, 12503f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent .direction_output = stmpe_gpio_direction_output, 12603f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent .set = stmpe_gpio_set, 12703f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent .to_irq = stmpe_gpio_to_irq, 12803f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent .request = stmpe_gpio_request, 12903f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent .can_sleep = 1, 13003f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent}; 13103f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent 1322a866f39146a5613d5c2db9031c13c218a4c7402Lennert Buytenhekstatic int stmpe_gpio_irq_set_type(struct irq_data *d, unsigned int type) 13303f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent{ 1342a866f39146a5613d5c2db9031c13c218a4c7402Lennert Buytenhek struct stmpe_gpio *stmpe_gpio = irq_data_get_irq_chip_data(d); 1352a866f39146a5613d5c2db9031c13c218a4c7402Lennert Buytenhek int offset = d->irq - stmpe_gpio->irq_base; 13603f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent int regoffset = offset / 8; 13703f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent int mask = 1 << (offset % 8); 13803f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent 13903f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent if (type == IRQ_TYPE_LEVEL_LOW || type == IRQ_TYPE_LEVEL_HIGH) 14003f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent return -EINVAL; 14103f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent 142cccdceb938b37a415c42a0635b8a19893a3a19bbViresh Kumar /* STMPE801 doesn't have RE and FE registers */ 143cccdceb938b37a415c42a0635b8a19893a3a19bbViresh Kumar if (stmpe_gpio->stmpe->partnum == STMPE801) 144cccdceb938b37a415c42a0635b8a19893a3a19bbViresh Kumar return 0; 145cccdceb938b37a415c42a0635b8a19893a3a19bbViresh Kumar 14603f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent if (type == IRQ_TYPE_EDGE_RISING) 14703f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent stmpe_gpio->regs[REG_RE][regoffset] |= mask; 14803f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent else 14903f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent stmpe_gpio->regs[REG_RE][regoffset] &= ~mask; 15003f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent 15103f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent if (type == IRQ_TYPE_EDGE_FALLING) 15203f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent stmpe_gpio->regs[REG_FE][regoffset] |= mask; 15303f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent else 15403f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent stmpe_gpio->regs[REG_FE][regoffset] &= ~mask; 15503f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent 15603f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent return 0; 15703f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent} 15803f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent 1592a866f39146a5613d5c2db9031c13c218a4c7402Lennert Buytenhekstatic void stmpe_gpio_irq_lock(struct irq_data *d) 16003f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent{ 1612a866f39146a5613d5c2db9031c13c218a4c7402Lennert Buytenhek struct stmpe_gpio *stmpe_gpio = irq_data_get_irq_chip_data(d); 16203f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent 16303f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent mutex_lock(&stmpe_gpio->irq_lock); 16403f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent} 16503f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent 1662a866f39146a5613d5c2db9031c13c218a4c7402Lennert Buytenhekstatic void stmpe_gpio_irq_sync_unlock(struct irq_data *d) 16703f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent{ 1682a866f39146a5613d5c2db9031c13c218a4c7402Lennert Buytenhek struct stmpe_gpio *stmpe_gpio = irq_data_get_irq_chip_data(d); 16903f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent struct stmpe *stmpe = stmpe_gpio->stmpe; 17003f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent int num_banks = DIV_ROUND_UP(stmpe->num_gpios, 8); 17103f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent static const u8 regmap[] = { 17203f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent [REG_RE] = STMPE_IDX_GPRER_LSB, 17303f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent [REG_FE] = STMPE_IDX_GPFER_LSB, 17403f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent [REG_IE] = STMPE_IDX_IEGPIOR_LSB, 17503f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent }; 17603f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent int i, j; 17703f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent 17803f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent for (i = 0; i < CACHE_NR_REGS; i++) { 179cccdceb938b37a415c42a0635b8a19893a3a19bbViresh Kumar /* STMPE801 doesn't have RE and FE registers */ 180cccdceb938b37a415c42a0635b8a19893a3a19bbViresh Kumar if ((stmpe->partnum == STMPE801) && 181cccdceb938b37a415c42a0635b8a19893a3a19bbViresh Kumar (i != REG_IE)) 182cccdceb938b37a415c42a0635b8a19893a3a19bbViresh Kumar continue; 183cccdceb938b37a415c42a0635b8a19893a3a19bbViresh Kumar 18403f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent for (j = 0; j < num_banks; j++) { 18503f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent u8 old = stmpe_gpio->oldregs[i][j]; 18603f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent u8 new = stmpe_gpio->regs[i][j]; 18703f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent 18803f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent if (new == old) 18903f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent continue; 19003f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent 19103f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent stmpe_gpio->oldregs[i][j] = new; 19203f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent stmpe_reg_write(stmpe, stmpe->regs[regmap[i]] - j, new); 19303f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent } 19403f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent } 19503f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent 19603f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent mutex_unlock(&stmpe_gpio->irq_lock); 19703f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent} 19803f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent 1992a866f39146a5613d5c2db9031c13c218a4c7402Lennert Buytenhekstatic void stmpe_gpio_irq_mask(struct irq_data *d) 20003f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent{ 2012a866f39146a5613d5c2db9031c13c218a4c7402Lennert Buytenhek struct stmpe_gpio *stmpe_gpio = irq_data_get_irq_chip_data(d); 2022a866f39146a5613d5c2db9031c13c218a4c7402Lennert Buytenhek int offset = d->irq - stmpe_gpio->irq_base; 20303f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent int regoffset = offset / 8; 20403f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent int mask = 1 << (offset % 8); 20503f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent 20603f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent stmpe_gpio->regs[REG_IE][regoffset] &= ~mask; 20703f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent} 20803f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent 2092a866f39146a5613d5c2db9031c13c218a4c7402Lennert Buytenhekstatic void stmpe_gpio_irq_unmask(struct irq_data *d) 21003f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent{ 2112a866f39146a5613d5c2db9031c13c218a4c7402Lennert Buytenhek struct stmpe_gpio *stmpe_gpio = irq_data_get_irq_chip_data(d); 2122a866f39146a5613d5c2db9031c13c218a4c7402Lennert Buytenhek int offset = d->irq - stmpe_gpio->irq_base; 21303f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent int regoffset = offset / 8; 21403f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent int mask = 1 << (offset % 8); 21503f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent 21603f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent stmpe_gpio->regs[REG_IE][regoffset] |= mask; 21703f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent} 21803f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent 21903f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincentstatic struct irq_chip stmpe_gpio_irq_chip = { 22003f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent .name = "stmpe-gpio", 2212a866f39146a5613d5c2db9031c13c218a4c7402Lennert Buytenhek .irq_bus_lock = stmpe_gpio_irq_lock, 2222a866f39146a5613d5c2db9031c13c218a4c7402Lennert Buytenhek .irq_bus_sync_unlock = stmpe_gpio_irq_sync_unlock, 2232a866f39146a5613d5c2db9031c13c218a4c7402Lennert Buytenhek .irq_mask = stmpe_gpio_irq_mask, 2242a866f39146a5613d5c2db9031c13c218a4c7402Lennert Buytenhek .irq_unmask = stmpe_gpio_irq_unmask, 2252a866f39146a5613d5c2db9031c13c218a4c7402Lennert Buytenhek .irq_set_type = stmpe_gpio_irq_set_type, 22603f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent}; 22703f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent 22803f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincentstatic irqreturn_t stmpe_gpio_irq(int irq, void *dev) 22903f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent{ 23003f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent struct stmpe_gpio *stmpe_gpio = dev; 23103f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent struct stmpe *stmpe = stmpe_gpio->stmpe; 23203f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent u8 statmsbreg = stmpe->regs[STMPE_IDX_ISGPIOR_MSB]; 23303f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent int num_banks = DIV_ROUND_UP(stmpe->num_gpios, 8); 23403f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent u8 status[num_banks]; 23503f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent int ret; 23603f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent int i; 23703f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent 23803f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent ret = stmpe_block_read(stmpe, statmsbreg, num_banks, status); 23903f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent if (ret < 0) 24003f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent return IRQ_NONE; 24103f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent 24203f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent for (i = 0; i < num_banks; i++) { 24303f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent int bank = num_banks - i - 1; 24403f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent unsigned int enabled = stmpe_gpio->regs[REG_IE][bank]; 24503f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent unsigned int stat = status[i]; 24603f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent 24703f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent stat &= enabled; 24803f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent if (!stat) 24903f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent continue; 25003f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent 25103f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent while (stat) { 25203f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent int bit = __ffs(stat); 25303f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent int line = bank * 8 + bit; 25403f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent 25503f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent handle_nested_irq(stmpe_gpio->irq_base + line); 25603f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent stat &= ~(1 << bit); 25703f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent } 25803f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent 25903f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent stmpe_reg_write(stmpe, statmsbreg + i, status[i]); 260cccdceb938b37a415c42a0635b8a19893a3a19bbViresh Kumar 261cccdceb938b37a415c42a0635b8a19893a3a19bbViresh Kumar /* Edge detect register is not present on 801 */ 262cccdceb938b37a415c42a0635b8a19893a3a19bbViresh Kumar if (stmpe->partnum != STMPE801) 263cccdceb938b37a415c42a0635b8a19893a3a19bbViresh Kumar stmpe_reg_write(stmpe, stmpe->regs[STMPE_IDX_GPEDR_MSB] 264cccdceb938b37a415c42a0635b8a19893a3a19bbViresh Kumar + i, status[i]); 26503f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent } 26603f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent 26703f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent return IRQ_HANDLED; 26803f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent} 26903f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent 27003f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincentstatic int __devinit stmpe_gpio_irq_init(struct stmpe_gpio *stmpe_gpio) 27103f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent{ 27203f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent int base = stmpe_gpio->irq_base; 27303f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent int irq; 27403f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent 27503f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent for (irq = base; irq < base + stmpe_gpio->chip.ngpio; irq++) { 276b51804bcf0774a8bc6af1e8bb6ae818f4b71173aThomas Gleixner irq_set_chip_data(irq, stmpe_gpio); 277b51804bcf0774a8bc6af1e8bb6ae818f4b71173aThomas Gleixner irq_set_chip_and_handler(irq, &stmpe_gpio_irq_chip, 27803f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent handle_simple_irq); 279b51804bcf0774a8bc6af1e8bb6ae818f4b71173aThomas Gleixner irq_set_nested_thread(irq, 1); 28003f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent#ifdef CONFIG_ARM 28103f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent set_irq_flags(irq, IRQF_VALID); 28203f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent#else 283b51804bcf0774a8bc6af1e8bb6ae818f4b71173aThomas Gleixner irq_set_noprobe(irq); 28403f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent#endif 28503f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent } 28603f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent 28703f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent return 0; 28803f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent} 28903f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent 29003f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincentstatic void stmpe_gpio_irq_remove(struct stmpe_gpio *stmpe_gpio) 29103f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent{ 29203f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent int base = stmpe_gpio->irq_base; 29303f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent int irq; 29403f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent 29503f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent for (irq = base; irq < base + stmpe_gpio->chip.ngpio; irq++) { 29603f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent#ifdef CONFIG_ARM 29703f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent set_irq_flags(irq, 0); 29803f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent#endif 299b51804bcf0774a8bc6af1e8bb6ae818f4b71173aThomas Gleixner irq_set_chip_and_handler(irq, NULL, NULL); 300b51804bcf0774a8bc6af1e8bb6ae818f4b71173aThomas Gleixner irq_set_chip_data(irq, NULL); 30103f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent } 30203f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent} 30303f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent 30403f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincentstatic int __devinit stmpe_gpio_probe(struct platform_device *pdev) 30503f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent{ 30603f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent struct stmpe *stmpe = dev_get_drvdata(pdev->dev.parent); 30703f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent struct stmpe_gpio_platform_data *pdata; 30803f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent struct stmpe_gpio *stmpe_gpio; 30903f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent int ret; 31003f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent int irq; 31103f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent 31203f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent pdata = stmpe->pdata->gpio; 31303f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent 31403f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent irq = platform_get_irq(pdev, 0); 31503f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent if (irq < 0) 31603f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent return irq; 31703f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent 31803f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent stmpe_gpio = kzalloc(sizeof(struct stmpe_gpio), GFP_KERNEL); 31903f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent if (!stmpe_gpio) 32003f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent return -ENOMEM; 32103f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent 32203f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent mutex_init(&stmpe_gpio->irq_lock); 32303f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent 32403f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent stmpe_gpio->dev = &pdev->dev; 32503f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent stmpe_gpio->stmpe = stmpe; 326b8e9cf0b28173fc25dae9f3ac44de6fc4e9fc385Wolfram Sang stmpe_gpio->norequest_mask = pdata ? pdata->norequest_mask : 0; 32703f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent 32803f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent stmpe_gpio->chip = template_chip; 32903f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent stmpe_gpio->chip.ngpio = stmpe->num_gpios; 33003f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent stmpe_gpio->chip.dev = &pdev->dev; 33103f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent stmpe_gpio->chip.base = pdata ? pdata->gpio_base : -1; 33203f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent 33303f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent stmpe_gpio->irq_base = stmpe->irq_base + STMPE_INT_GPIO(0); 33403f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent 33503f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent ret = stmpe_enable(stmpe, STMPE_BLOCK_GPIO); 33603f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent if (ret) 33702bf07492341d94e29890082201dd69dbf406570Vasiliy Kulikov goto out_free; 33803f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent 33903f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent ret = stmpe_gpio_irq_init(stmpe_gpio); 34003f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent if (ret) 34102bf07492341d94e29890082201dd69dbf406570Vasiliy Kulikov goto out_disable; 34203f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent 34303f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent ret = request_threaded_irq(irq, NULL, stmpe_gpio_irq, IRQF_ONESHOT, 34403f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent "stmpe-gpio", stmpe_gpio); 34503f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent if (ret) { 34603f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent dev_err(&pdev->dev, "unable to get irq: %d\n", ret); 34703f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent goto out_removeirq; 34803f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent } 34903f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent 35003f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent ret = gpiochip_add(&stmpe_gpio->chip); 35103f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent if (ret) { 35203f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent dev_err(&pdev->dev, "unable to add gpiochip: %d\n", ret); 35303f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent goto out_freeirq; 35403f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent } 35503f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent 35603f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent if (pdata && pdata->setup) 35703f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent pdata->setup(stmpe, stmpe_gpio->chip.base); 35803f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent 35903f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent platform_set_drvdata(pdev, stmpe_gpio); 36003f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent 36103f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent return 0; 36203f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent 36303f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincentout_freeirq: 36403f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent free_irq(irq, stmpe_gpio); 36503f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincentout_removeirq: 36603f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent stmpe_gpio_irq_remove(stmpe_gpio); 36702bf07492341d94e29890082201dd69dbf406570Vasiliy Kulikovout_disable: 36802bf07492341d94e29890082201dd69dbf406570Vasiliy Kulikov stmpe_disable(stmpe, STMPE_BLOCK_GPIO); 36903f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincentout_free: 37003f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent kfree(stmpe_gpio); 37103f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent return ret; 37203f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent} 37303f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent 37403f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincentstatic int __devexit stmpe_gpio_remove(struct platform_device *pdev) 37503f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent{ 37603f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent struct stmpe_gpio *stmpe_gpio = platform_get_drvdata(pdev); 37703f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent struct stmpe *stmpe = stmpe_gpio->stmpe; 37803f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent struct stmpe_gpio_platform_data *pdata = stmpe->pdata->gpio; 37903f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent int irq = platform_get_irq(pdev, 0); 38003f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent int ret; 38103f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent 38203f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent if (pdata && pdata->remove) 38303f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent pdata->remove(stmpe, stmpe_gpio->chip.base); 38403f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent 38503f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent ret = gpiochip_remove(&stmpe_gpio->chip); 38603f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent if (ret < 0) { 38703f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent dev_err(stmpe_gpio->dev, 38803f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent "unable to remove gpiochip: %d\n", ret); 38903f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent return ret; 39003f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent } 39103f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent 39203f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent stmpe_disable(stmpe, STMPE_BLOCK_GPIO); 39303f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent 39403f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent free_irq(irq, stmpe_gpio); 39503f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent stmpe_gpio_irq_remove(stmpe_gpio); 39603f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent platform_set_drvdata(pdev, NULL); 39703f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent kfree(stmpe_gpio); 39803f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent 39903f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent return 0; 40003f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent} 40103f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent 40203f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincentstatic struct platform_driver stmpe_gpio_driver = { 40303f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent .driver.name = "stmpe-gpio", 40403f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent .driver.owner = THIS_MODULE, 40503f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent .probe = stmpe_gpio_probe, 40603f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent .remove = __devexit_p(stmpe_gpio_remove), 40703f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent}; 40803f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent 40903f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincentstatic int __init stmpe_gpio_init(void) 41003f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent{ 41103f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent return platform_driver_register(&stmpe_gpio_driver); 41203f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent} 41303f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincentsubsys_initcall(stmpe_gpio_init); 41403f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent 41503f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincentstatic void __exit stmpe_gpio_exit(void) 41603f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent{ 41703f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent platform_driver_unregister(&stmpe_gpio_driver); 41803f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent} 41903f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincentmodule_exit(stmpe_gpio_exit); 42003f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin Vincent 42103f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin VincentMODULE_LICENSE("GPL v2"); 42203f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin VincentMODULE_DESCRIPTION("STMPExxxx GPIO driver"); 42303f822f5e5f5924f4ad372d3e698855c6a9275e0Rabin VincentMODULE_AUTHOR("Rabin Vincent <rabin.vincent@stericsson.com>"); 424