aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mfd/stmpe.c
diff options
context:
space:
mode:
authorJean-Nicolas Graux <jean-nicolas.graux@stericsson.com>2013-04-09 04:35:19 -0400
committerSamuel Ortiz <sameo@linux.intel.com>2013-04-09 08:15:58 -0400
commit230f13a5035fd4725a6623af83953623fd51173a (patch)
treeedc40619999feffbb4fa74c02d5faed228aae1b1 /drivers/mfd/stmpe.c
parente65ad41e3b3f28316565ad0061b8152a3a8227ba (diff)
mfd: support stmpe1801 18 bits enhanced port expander
Provides support for 1801 variant of stmpe gpio port expanders. This chip has 18 gpios configurable as GPI, GPO, keypad matrix, special key or dedicated key function. Note that special/dedicated key function is not supported yet. Signed-off-by: Jean-Nicolas Graux <jean-nicolas.graux@stericsson.com> Acked-by: Linus Walleij <linus.walleij@linaro.org> Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
Diffstat (limited to 'drivers/mfd/stmpe.c')
-rw-r--r--drivers/mfd/stmpe.c97
1 files changed, 96 insertions, 1 deletions
diff --git a/drivers/mfd/stmpe.c b/drivers/mfd/stmpe.c
index bc8587777993..bbccd514d3ec 100644
--- a/drivers/mfd/stmpe.c
+++ b/drivers/mfd/stmpe.c
@@ -19,6 +19,7 @@
19#include <linux/pm.h> 19#include <linux/pm.h>
20#include <linux/slab.h> 20#include <linux/slab.h>
21#include <linux/mfd/core.h> 21#include <linux/mfd/core.h>
22#include <linux/delay.h>
22#include "stmpe.h" 23#include "stmpe.h"
23 24
24static int __stmpe_enable(struct stmpe *stmpe, unsigned int blocks) 25static int __stmpe_enable(struct stmpe *stmpe, unsigned int blocks)
@@ -643,6 +644,88 @@ static struct stmpe_variant_info stmpe1601 = {
643}; 644};
644 645
645/* 646/*
647 * STMPE1801
648 */
649static const u8 stmpe1801_regs[] = {
650 [STMPE_IDX_CHIP_ID] = STMPE1801_REG_CHIP_ID,
651 [STMPE_IDX_ICR_LSB] = STMPE1801_REG_INT_CTRL_LOW,
652 [STMPE_IDX_IER_LSB] = STMPE1801_REG_INT_EN_MASK_LOW,
653 [STMPE_IDX_ISR_LSB] = STMPE1801_REG_INT_STA_LOW,
654 [STMPE_IDX_GPMR_LSB] = STMPE1801_REG_GPIO_MP_LOW,
655 [STMPE_IDX_GPSR_LSB] = STMPE1801_REG_GPIO_SET_LOW,
656 [STMPE_IDX_GPCR_LSB] = STMPE1801_REG_GPIO_CLR_LOW,
657 [STMPE_IDX_GPDR_LSB] = STMPE1801_REG_GPIO_SET_DIR_LOW,
658 [STMPE_IDX_GPRER_LSB] = STMPE1801_REG_GPIO_RE_LOW,
659 [STMPE_IDX_GPFER_LSB] = STMPE1801_REG_GPIO_FE_LOW,
660 [STMPE_IDX_IEGPIOR_LSB] = STMPE1801_REG_INT_EN_GPIO_MASK_LOW,
661 [STMPE_IDX_ISGPIOR_LSB] = STMPE1801_REG_INT_STA_GPIO_LOW,
662};
663
664static struct stmpe_variant_block stmpe1801_blocks[] = {
665 {
666 .cell = &stmpe_gpio_cell,
667 .irq = STMPE1801_IRQ_GPIOC,
668 .block = STMPE_BLOCK_GPIO,
669 },
670 {
671 .cell = &stmpe_keypad_cell,
672 .irq = STMPE1801_IRQ_KEYPAD,
673 .block = STMPE_BLOCK_KEYPAD,
674 },
675};
676
677static int stmpe1801_enable(struct stmpe *stmpe, unsigned int blocks,
678 bool enable)
679{
680 unsigned int mask = 0;
681 if (blocks & STMPE_BLOCK_GPIO)
682 mask |= STMPE1801_MSK_INT_EN_GPIO;
683
684 if (blocks & STMPE_BLOCK_KEYPAD)
685 mask |= STMPE1801_MSK_INT_EN_KPC;
686
687 return __stmpe_set_bits(stmpe, STMPE1801_REG_INT_EN_MASK_LOW, mask,
688 enable ? mask : 0);
689}
690
691static int stmpe1801_reset(struct stmpe *stmpe)
692{
693 unsigned long timeout;
694 int ret = 0;
695
696 ret = __stmpe_set_bits(stmpe, STMPE1801_REG_SYS_CTRL,
697 STMPE1801_MSK_SYS_CTRL_RESET, STMPE1801_MSK_SYS_CTRL_RESET);
698 if (ret < 0)
699 return ret;
700
701 timeout = jiffies + msecs_to_jiffies(100);
702 while (time_before(jiffies, timeout)) {
703 ret = __stmpe_reg_read(stmpe, STMPE1801_REG_SYS_CTRL);
704 if (ret < 0)
705 return ret;
706 if (!(ret & STMPE1801_MSK_SYS_CTRL_RESET))
707 return 0;
708 usleep_range(100, 200);
709 };
710 return -EIO;
711}
712
713static struct stmpe_variant_info stmpe1801 = {
714 .name = "stmpe1801",
715 .id_val = STMPE1801_ID,
716 .id_mask = 0xfff0,
717 .num_gpios = 18,
718 .af_bits = 0,
719 .regs = stmpe1801_regs,
720 .blocks = stmpe1801_blocks,
721 .num_blocks = ARRAY_SIZE(stmpe1801_blocks),
722 .num_irqs = STMPE1801_NR_INTERNAL_IRQS,
723 .enable = stmpe1801_enable,
724 /* stmpe1801 do not have any gpio alternate function */
725 .get_altfunc = NULL,
726};
727
728/*
646 * STMPE24XX 729 * STMPE24XX
647 */ 730 */
648 731
@@ -740,6 +823,7 @@ static struct stmpe_variant_info *stmpe_variant_info[STMPE_NBR_PARTS] = {
740 [STMPE801] = &stmpe801, 823 [STMPE801] = &stmpe801,
741 [STMPE811] = &stmpe811, 824 [STMPE811] = &stmpe811,
742 [STMPE1601] = &stmpe1601, 825 [STMPE1601] = &stmpe1601,
826 [STMPE1801] = &stmpe1801,
743 [STMPE2401] = &stmpe2401, 827 [STMPE2401] = &stmpe2401,
744 [STMPE2403] = &stmpe2403, 828 [STMPE2403] = &stmpe2403,
745}; 829};
@@ -759,7 +843,7 @@ static irqreturn_t stmpe_irq(int irq, void *data)
759 struct stmpe *stmpe = data; 843 struct stmpe *stmpe = data;
760 struct stmpe_variant_info *variant = stmpe->variant; 844 struct stmpe_variant_info *variant = stmpe->variant;
761 int num = DIV_ROUND_UP(variant->num_irqs, 8); 845 int num = DIV_ROUND_UP(variant->num_irqs, 8);
762 u8 israddr = stmpe->regs[STMPE_IDX_ISR_MSB]; 846 u8 israddr;
763 u8 isr[num]; 847 u8 isr[num];
764 int ret; 848 int ret;
765 int i; 849 int i;
@@ -771,6 +855,11 @@ static irqreturn_t stmpe_irq(int irq, void *data)
771 return IRQ_HANDLED; 855 return IRQ_HANDLED;
772 } 856 }
773 857
858 if (variant->id_val == STMPE1801_ID)
859 israddr = stmpe->regs[STMPE_IDX_ISR_LSB];
860 else
861 israddr = stmpe->regs[STMPE_IDX_ISR_MSB];
862
774 ret = stmpe_block_read(stmpe, israddr, num, isr); 863 ret = stmpe_block_read(stmpe, israddr, num, isr);
775 if (ret < 0) 864 if (ret < 0)
776 return IRQ_NONE; 865 return IRQ_NONE;
@@ -938,6 +1027,12 @@ static int stmpe_chip_init(struct stmpe *stmpe)
938 if (ret) 1027 if (ret)
939 return ret; 1028 return ret;
940 1029
1030 if (id == STMPE1801_ID) {
1031 ret = stmpe1801_reset(stmpe);
1032 if (ret < 0)
1033 return ret;
1034 }
1035
941 if (stmpe->irq >= 0) { 1036 if (stmpe->irq >= 0) {
942 if (id == STMPE801_ID) 1037 if (id == STMPE801_ID)
943 icr = STMPE801_REG_SYS_CTRL_INT_EN; 1038 icr = STMPE801_REG_SYS_CTRL_INT_EN;