diff options
Diffstat (limited to 'drivers/mfd/stmpe.c')
-rw-r--r-- | drivers/mfd/stmpe.c | 134 |
1 files changed, 96 insertions, 38 deletions
diff --git a/drivers/mfd/stmpe.c b/drivers/mfd/stmpe.c index e07947e56b2a..2dd8d49cb30b 100644 --- a/drivers/mfd/stmpe.c +++ b/drivers/mfd/stmpe.c | |||
@@ -298,6 +298,11 @@ static struct mfd_cell stmpe_gpio_cell = { | |||
298 | .num_resources = ARRAY_SIZE(stmpe_gpio_resources), | 298 | .num_resources = ARRAY_SIZE(stmpe_gpio_resources), |
299 | }; | 299 | }; |
300 | 300 | ||
301 | static struct mfd_cell stmpe_gpio_cell_noirq = { | ||
302 | .name = "stmpe-gpio", | ||
303 | /* gpio cell resources consist of an irq only so no resources here */ | ||
304 | }; | ||
305 | |||
301 | /* | 306 | /* |
302 | * Keypad (1601, 2401, 2403) | 307 | * Keypad (1601, 2401, 2403) |
303 | */ | 308 | */ |
@@ -346,6 +351,13 @@ static struct stmpe_variant_block stmpe801_blocks[] = { | |||
346 | }, | 351 | }, |
347 | }; | 352 | }; |
348 | 353 | ||
354 | static struct stmpe_variant_block stmpe801_blocks_noirq[] = { | ||
355 | { | ||
356 | .cell = &stmpe_gpio_cell_noirq, | ||
357 | .block = STMPE_BLOCK_GPIO, | ||
358 | }, | ||
359 | }; | ||
360 | |||
349 | static int stmpe801_enable(struct stmpe *stmpe, unsigned int blocks, | 361 | static int stmpe801_enable(struct stmpe *stmpe, unsigned int blocks, |
350 | bool enable) | 362 | bool enable) |
351 | { | 363 | { |
@@ -367,6 +379,17 @@ static struct stmpe_variant_info stmpe801 = { | |||
367 | .enable = stmpe801_enable, | 379 | .enable = stmpe801_enable, |
368 | }; | 380 | }; |
369 | 381 | ||
382 | static struct stmpe_variant_info stmpe801_noirq = { | ||
383 | .name = "stmpe801", | ||
384 | .id_val = STMPE801_ID, | ||
385 | .id_mask = 0xffff, | ||
386 | .num_gpios = 8, | ||
387 | .regs = stmpe801_regs, | ||
388 | .blocks = stmpe801_blocks_noirq, | ||
389 | .num_blocks = ARRAY_SIZE(stmpe801_blocks_noirq), | ||
390 | .enable = stmpe801_enable, | ||
391 | }; | ||
392 | |||
370 | /* | 393 | /* |
371 | * Touchscreen (STMPE811 or STMPE610) | 394 | * Touchscreen (STMPE811 or STMPE610) |
372 | */ | 395 | */ |
@@ -712,7 +735,7 @@ static struct stmpe_variant_info stmpe2403 = { | |||
712 | .enable_autosleep = stmpe1601_autosleep, /* same as stmpe1601 */ | 735 | .enable_autosleep = stmpe1601_autosleep, /* same as stmpe1601 */ |
713 | }; | 736 | }; |
714 | 737 | ||
715 | static struct stmpe_variant_info *stmpe_variant_info[] = { | 738 | static struct stmpe_variant_info *stmpe_variant_info[STMPE_NBR_PARTS] = { |
716 | [STMPE610] = &stmpe610, | 739 | [STMPE610] = &stmpe610, |
717 | [STMPE801] = &stmpe801, | 740 | [STMPE801] = &stmpe801, |
718 | [STMPE811] = &stmpe811, | 741 | [STMPE811] = &stmpe811, |
@@ -721,6 +744,16 @@ static struct stmpe_variant_info *stmpe_variant_info[] = { | |||
721 | [STMPE2403] = &stmpe2403, | 744 | [STMPE2403] = &stmpe2403, |
722 | }; | 745 | }; |
723 | 746 | ||
747 | /* | ||
748 | * These devices can be connected in a 'no-irq' configuration - the irq pin | ||
749 | * is not used and the device cannot interrupt the CPU. Here we only list | ||
750 | * devices which support this configuration - the driver will fail probing | ||
751 | * for any devices not listed here which are configured in this way. | ||
752 | */ | ||
753 | static struct stmpe_variant_info *stmpe_noirq_variant_info[STMPE_NBR_PARTS] = { | ||
754 | [STMPE801] = &stmpe801_noirq, | ||
755 | }; | ||
756 | |||
724 | static irqreturn_t stmpe_irq(int irq, void *data) | 757 | static irqreturn_t stmpe_irq(int irq, void *data) |
725 | { | 758 | { |
726 | struct stmpe *stmpe = data; | 759 | struct stmpe *stmpe = data; |
@@ -864,7 +897,7 @@ static int __devinit stmpe_chip_init(struct stmpe *stmpe) | |||
864 | unsigned int irq_trigger = stmpe->pdata->irq_trigger; | 897 | unsigned int irq_trigger = stmpe->pdata->irq_trigger; |
865 | int autosleep_timeout = stmpe->pdata->autosleep_timeout; | 898 | int autosleep_timeout = stmpe->pdata->autosleep_timeout; |
866 | struct stmpe_variant_info *variant = stmpe->variant; | 899 | struct stmpe_variant_info *variant = stmpe->variant; |
867 | u8 icr; | 900 | u8 icr = 0; |
868 | unsigned int id; | 901 | unsigned int id; |
869 | u8 data[2]; | 902 | u8 data[2]; |
870 | int ret; | 903 | int ret; |
@@ -887,31 +920,33 @@ static int __devinit stmpe_chip_init(struct stmpe *stmpe) | |||
887 | if (ret) | 920 | if (ret) |
888 | return ret; | 921 | return ret; |
889 | 922 | ||
890 | if (id == STMPE801_ID) | 923 | if (stmpe->irq >= 0) { |
891 | icr = STMPE801_REG_SYS_CTRL_INT_EN; | ||
892 | else | ||
893 | icr = STMPE_ICR_LSB_GIM; | ||
894 | |||
895 | /* STMPE801 doesn't support Edge interrupts */ | ||
896 | if (id != STMPE801_ID) { | ||
897 | if (irq_trigger == IRQF_TRIGGER_FALLING || | ||
898 | irq_trigger == IRQF_TRIGGER_RISING) | ||
899 | icr |= STMPE_ICR_LSB_EDGE; | ||
900 | } | ||
901 | |||
902 | if (irq_trigger == IRQF_TRIGGER_RISING || | ||
903 | irq_trigger == IRQF_TRIGGER_HIGH) { | ||
904 | if (id == STMPE801_ID) | 924 | if (id == STMPE801_ID) |
905 | icr |= STMPE801_REG_SYS_CTRL_INT_HI; | 925 | icr = STMPE801_REG_SYS_CTRL_INT_EN; |
906 | else | 926 | else |
907 | icr |= STMPE_ICR_LSB_HIGH; | 927 | icr = STMPE_ICR_LSB_GIM; |
908 | } | ||
909 | 928 | ||
910 | if (stmpe->pdata->irq_invert_polarity) { | 929 | /* STMPE801 doesn't support Edge interrupts */ |
911 | if (id == STMPE801_ID) | 930 | if (id != STMPE801_ID) { |
912 | icr ^= STMPE801_REG_SYS_CTRL_INT_HI; | 931 | if (irq_trigger == IRQF_TRIGGER_FALLING || |
913 | else | 932 | irq_trigger == IRQF_TRIGGER_RISING) |
914 | icr ^= STMPE_ICR_LSB_HIGH; | 933 | icr |= STMPE_ICR_LSB_EDGE; |
934 | } | ||
935 | |||
936 | if (irq_trigger == IRQF_TRIGGER_RISING || | ||
937 | irq_trigger == IRQF_TRIGGER_HIGH) { | ||
938 | if (id == STMPE801_ID) | ||
939 | icr |= STMPE801_REG_SYS_CTRL_INT_HI; | ||
940 | else | ||
941 | icr |= STMPE_ICR_LSB_HIGH; | ||
942 | } | ||
943 | |||
944 | if (stmpe->pdata->irq_invert_polarity) { | ||
945 | if (id == STMPE801_ID) | ||
946 | icr ^= STMPE801_REG_SYS_CTRL_INT_HI; | ||
947 | else | ||
948 | icr ^= STMPE_ICR_LSB_HIGH; | ||
949 | } | ||
915 | } | 950 | } |
916 | 951 | ||
917 | if (stmpe->pdata->autosleep) { | 952 | if (stmpe->pdata->autosleep) { |
@@ -1001,19 +1036,38 @@ int __devinit stmpe_probe(struct stmpe_client_info *ci, int partnum) | |||
1001 | stmpe->irq = ci->irq; | 1036 | stmpe->irq = ci->irq; |
1002 | } | 1037 | } |
1003 | 1038 | ||
1039 | if (stmpe->irq < 0) { | ||
1040 | /* use alternate variant info for no-irq mode, if supported */ | ||
1041 | dev_info(stmpe->dev, | ||
1042 | "%s configured in no-irq mode by platform data\n", | ||
1043 | stmpe->variant->name); | ||
1044 | if (!stmpe_noirq_variant_info[stmpe->partnum]) { | ||
1045 | dev_err(stmpe->dev, | ||
1046 | "%s does not support no-irq mode!\n", | ||
1047 | stmpe->variant->name); | ||
1048 | ret = -ENODEV; | ||
1049 | goto free_gpio; | ||
1050 | } | ||
1051 | stmpe->variant = stmpe_noirq_variant_info[stmpe->partnum]; | ||
1052 | } | ||
1053 | |||
1004 | ret = stmpe_chip_init(stmpe); | 1054 | ret = stmpe_chip_init(stmpe); |
1005 | if (ret) | 1055 | if (ret) |
1006 | goto free_gpio; | 1056 | goto free_gpio; |
1007 | 1057 | ||
1008 | ret = stmpe_irq_init(stmpe); | 1058 | if (stmpe->irq >= 0) { |
1009 | if (ret) | 1059 | ret = stmpe_irq_init(stmpe); |
1010 | goto free_gpio; | 1060 | if (ret) |
1061 | goto free_gpio; | ||
1011 | 1062 | ||
1012 | ret = request_threaded_irq(stmpe->irq, NULL, stmpe_irq, | 1063 | ret = request_threaded_irq(stmpe->irq, NULL, stmpe_irq, |
1013 | pdata->irq_trigger | IRQF_ONESHOT, "stmpe", stmpe); | 1064 | pdata->irq_trigger | IRQF_ONESHOT, |
1014 | if (ret) { | 1065 | "stmpe", stmpe); |
1015 | dev_err(stmpe->dev, "failed to request IRQ: %d\n", ret); | 1066 | if (ret) { |
1016 | goto out_removeirq; | 1067 | dev_err(stmpe->dev, "failed to request IRQ: %d\n", |
1068 | ret); | ||
1069 | goto out_removeirq; | ||
1070 | } | ||
1017 | } | 1071 | } |
1018 | 1072 | ||
1019 | ret = stmpe_devices_init(stmpe); | 1073 | ret = stmpe_devices_init(stmpe); |
@@ -1026,9 +1080,11 @@ int __devinit stmpe_probe(struct stmpe_client_info *ci, int partnum) | |||
1026 | 1080 | ||
1027 | out_removedevs: | 1081 | out_removedevs: |
1028 | mfd_remove_devices(stmpe->dev); | 1082 | mfd_remove_devices(stmpe->dev); |
1029 | free_irq(stmpe->irq, stmpe); | 1083 | if (stmpe->irq >= 0) |
1084 | free_irq(stmpe->irq, stmpe); | ||
1030 | out_removeirq: | 1085 | out_removeirq: |
1031 | stmpe_irq_remove(stmpe); | 1086 | if (stmpe->irq >= 0) |
1087 | stmpe_irq_remove(stmpe); | ||
1032 | free_gpio: | 1088 | free_gpio: |
1033 | if (pdata->irq_over_gpio) | 1089 | if (pdata->irq_over_gpio) |
1034 | gpio_free(pdata->irq_gpio); | 1090 | gpio_free(pdata->irq_gpio); |
@@ -1041,8 +1097,10 @@ int stmpe_remove(struct stmpe *stmpe) | |||
1041 | { | 1097 | { |
1042 | mfd_remove_devices(stmpe->dev); | 1098 | mfd_remove_devices(stmpe->dev); |
1043 | 1099 | ||
1044 | free_irq(stmpe->irq, stmpe); | 1100 | if (stmpe->irq >= 0) { |
1045 | stmpe_irq_remove(stmpe); | 1101 | free_irq(stmpe->irq, stmpe); |
1102 | stmpe_irq_remove(stmpe); | ||
1103 | } | ||
1046 | 1104 | ||
1047 | if (stmpe->pdata->irq_over_gpio) | 1105 | if (stmpe->pdata->irq_over_gpio) |
1048 | gpio_free(stmpe->pdata->irq_gpio); | 1106 | gpio_free(stmpe->pdata->irq_gpio); |
@@ -1057,7 +1115,7 @@ static int stmpe_suspend(struct device *dev) | |||
1057 | { | 1115 | { |
1058 | struct stmpe *stmpe = dev_get_drvdata(dev); | 1116 | struct stmpe *stmpe = dev_get_drvdata(dev); |
1059 | 1117 | ||
1060 | if (device_may_wakeup(dev)) | 1118 | if (stmpe->irq >= 0 && device_may_wakeup(dev)) |
1061 | enable_irq_wake(stmpe->irq); | 1119 | enable_irq_wake(stmpe->irq); |
1062 | 1120 | ||
1063 | return 0; | 1121 | return 0; |
@@ -1067,7 +1125,7 @@ static int stmpe_resume(struct device *dev) | |||
1067 | { | 1125 | { |
1068 | struct stmpe *stmpe = dev_get_drvdata(dev); | 1126 | struct stmpe *stmpe = dev_get_drvdata(dev); |
1069 | 1127 | ||
1070 | if (device_may_wakeup(dev)) | 1128 | if (stmpe->irq >= 0 && device_may_wakeup(dev)) |
1071 | disable_irq_wake(stmpe->irq); | 1129 | disable_irq_wake(stmpe->irq); |
1072 | 1130 | ||
1073 | return 0; | 1131 | return 0; |