diff options
Diffstat (limited to 'drivers/mfd/stmpe.c')
-rw-r--r-- | drivers/mfd/stmpe.c | 105 |
1 files changed, 103 insertions, 2 deletions
diff --git a/drivers/mfd/stmpe.c b/drivers/mfd/stmpe.c index 4b11202061be..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 | ||
24 | static int __stmpe_enable(struct stmpe *stmpe, unsigned int blocks) | 25 | static 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 | */ | ||
649 | static 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 | |||
664 | static 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 | |||
677 | static 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 | |||
691 | static 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 | |||
713 | static 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; |
@@ -1015,7 +1110,10 @@ void stmpe_of_probe(struct stmpe_platform_data *pdata, struct device_node *np) | |||
1015 | { | 1110 | { |
1016 | struct device_node *child; | 1111 | struct device_node *child; |
1017 | 1112 | ||
1018 | pdata->id = -1; | 1113 | pdata->id = of_alias_get_id(np, "stmpe-i2c"); |
1114 | if (pdata->id < 0) | ||
1115 | pdata->id = -1; | ||
1116 | |||
1019 | pdata->irq_trigger = IRQF_TRIGGER_NONE; | 1117 | pdata->irq_trigger = IRQF_TRIGGER_NONE; |
1020 | 1118 | ||
1021 | of_property_read_u32(np, "st,autosleep-timeout", | 1119 | of_property_read_u32(np, "st,autosleep-timeout", |
@@ -1057,6 +1155,9 @@ int stmpe_probe(struct stmpe_client_info *ci, int partnum) | |||
1057 | return -ENOMEM; | 1155 | return -ENOMEM; |
1058 | 1156 | ||
1059 | stmpe_of_probe(pdata, np); | 1157 | stmpe_of_probe(pdata, np); |
1158 | |||
1159 | if (of_find_property(np, "interrupts", NULL) == NULL) | ||
1160 | ci->irq = -1; | ||
1060 | } | 1161 | } |
1061 | 1162 | ||
1062 | stmpe = devm_kzalloc(ci->dev, sizeof(struct stmpe), GFP_KERNEL); | 1163 | stmpe = devm_kzalloc(ci->dev, sizeof(struct stmpe), GFP_KERNEL); |