diff options
-rw-r--r-- | drivers/extcon/Kconfig | 4 | ||||
-rw-r--r-- | drivers/extcon/extcon-max14577.c | 109 | ||||
-rw-r--r-- | drivers/mfd/max14577.c | 1 | ||||
-rw-r--r-- | include/linux/mfd/max14577-private.h | 3 |
4 files changed, 96 insertions, 21 deletions
diff --git a/drivers/extcon/Kconfig b/drivers/extcon/Kconfig index be56e8ac95e6..aebde489c291 100644 --- a/drivers/extcon/Kconfig +++ b/drivers/extcon/Kconfig | |||
@@ -28,13 +28,13 @@ config EXTCON_ADC_JACK | |||
28 | Say Y here to enable extcon device driver based on ADC values. | 28 | Say Y here to enable extcon device driver based on ADC values. |
29 | 29 | ||
30 | config EXTCON_MAX14577 | 30 | config EXTCON_MAX14577 |
31 | tristate "MAX14577 EXTCON Support" | 31 | tristate "MAX14577/77836 EXTCON Support" |
32 | depends on MFD_MAX14577 | 32 | depends on MFD_MAX14577 |
33 | select IRQ_DOMAIN | 33 | select IRQ_DOMAIN |
34 | select REGMAP_I2C | 34 | select REGMAP_I2C |
35 | help | 35 | help |
36 | If you say yes here you get support for the MUIC device of | 36 | If you say yes here you get support for the MUIC device of |
37 | Maxim MAX14577 PMIC. The MAX14577 MUIC is a USB port accessory | 37 | Maxim MAX14577/77836. The MAX14577/77836 MUIC is a USB port accessory |
38 | detector and switch. | 38 | detector and switch. |
39 | 39 | ||
40 | config EXTCON_MAX77693 | 40 | config EXTCON_MAX77693 |
diff --git a/drivers/extcon/extcon-max14577.c b/drivers/extcon/extcon-max14577.c index 1513013a92f1..c76734a70171 100644 --- a/drivers/extcon/extcon-max14577.c +++ b/drivers/extcon/extcon-max14577.c | |||
@@ -1,8 +1,9 @@ | |||
1 | /* | 1 | /* |
2 | * extcon-max14577.c - MAX14577 extcon driver to support MAX14577 MUIC | 2 | * extcon-max14577.c - MAX14577/77836 extcon driver to support MUIC |
3 | * | 3 | * |
4 | * Copyright (C) 2013 Samsung Electrnoics | 4 | * Copyright (C) 2013,2014 Samsung Electrnoics |
5 | * Chanwoo Choi <cw00.choi@samsung.com> | 5 | * Chanwoo Choi <cw00.choi@samsung.com> |
6 | * Krzysztof Kozlowski <k.kozlowski@samsung.com> | ||
6 | * | 7 | * |
7 | * This program is free software; you can redistribute it and/or modify | 8 | * This program is free software; you can redistribute it and/or modify |
8 | * it under the terms of the GNU General Public License as published by | 9 | * it under the terms of the GNU General Public License as published by |
@@ -62,6 +63,19 @@ static struct max14577_muic_irq max14577_muic_irqs[] = { | |||
62 | { MAX14577_IRQ_INT2_VBVOLT, "muic-VBVOLT" }, | 63 | { MAX14577_IRQ_INT2_VBVOLT, "muic-VBVOLT" }, |
63 | }; | 64 | }; |
64 | 65 | ||
66 | static struct max14577_muic_irq max77836_muic_irqs[] = { | ||
67 | { MAX14577_IRQ_INT1_ADC, "muic-ADC" }, | ||
68 | { MAX14577_IRQ_INT1_ADCLOW, "muic-ADCLOW" }, | ||
69 | { MAX14577_IRQ_INT1_ADCERR, "muic-ADCError" }, | ||
70 | { MAX77836_IRQ_INT1_ADC1K, "muic-ADC1K" }, | ||
71 | { MAX14577_IRQ_INT2_CHGTYP, "muic-CHGTYP" }, | ||
72 | { MAX14577_IRQ_INT2_CHGDETRUN, "muic-CHGDETRUN" }, | ||
73 | { MAX14577_IRQ_INT2_DCDTMR, "muic-DCDTMR" }, | ||
74 | { MAX14577_IRQ_INT2_DBCHG, "muic-DBCHG" }, | ||
75 | { MAX14577_IRQ_INT2_VBVOLT, "muic-VBVOLT" }, | ||
76 | { MAX77836_IRQ_INT2_VIDRM, "muic-VIDRM" }, | ||
77 | }; | ||
78 | |||
65 | struct max14577_muic_info { | 79 | struct max14577_muic_info { |
66 | struct device *dev; | 80 | struct device *dev; |
67 | struct max14577 *max14577; | 81 | struct max14577 *max14577; |
@@ -529,21 +543,12 @@ static void max14577_muic_irq_work(struct work_struct *work) | |||
529 | return; | 543 | return; |
530 | } | 544 | } |
531 | 545 | ||
532 | static irqreturn_t max14577_muic_irq_handler(int irq, void *data) | 546 | /* |
547 | * Sets irq_adc or irq_chg in max14577_muic_info and returns 1. | ||
548 | * Returns 0 if irq_type does not match registered IRQ for this device type. | ||
549 | */ | ||
550 | static int max14577_parse_irq(struct max14577_muic_info *info, int irq_type) | ||
533 | { | 551 | { |
534 | struct max14577_muic_info *info = data; | ||
535 | int i, irq_type = -1; | ||
536 | |||
537 | /* | ||
538 | * We may be called multiple times for different nested IRQ-s. | ||
539 | * Including changes in INT1_ADC and INT2_CGHTYP at once. | ||
540 | * However we only need to know whether it was ADC, charger | ||
541 | * or both interrupts so decode IRQ and turn on proper flags. | ||
542 | */ | ||
543 | for (i = 0; i < info->muic_irqs_num; i++) | ||
544 | if (irq == info->muic_irqs[i].virq) | ||
545 | irq_type = info->muic_irqs[i].irq; | ||
546 | |||
547 | switch (irq_type) { | 552 | switch (irq_type) { |
548 | case MAX14577_IRQ_INT1_ADC: | 553 | case MAX14577_IRQ_INT1_ADC: |
549 | case MAX14577_IRQ_INT1_ADCLOW: | 554 | case MAX14577_IRQ_INT1_ADCLOW: |
@@ -551,7 +556,7 @@ static irqreturn_t max14577_muic_irq_handler(int irq, void *data) | |||
551 | /* Handle all of accessory except for | 556 | /* Handle all of accessory except for |
552 | type of charger accessory */ | 557 | type of charger accessory */ |
553 | info->irq_adc = true; | 558 | info->irq_adc = true; |
554 | break; | 559 | return 1; |
555 | case MAX14577_IRQ_INT2_CHGTYP: | 560 | case MAX14577_IRQ_INT2_CHGTYP: |
556 | case MAX14577_IRQ_INT2_CHGDETRUN: | 561 | case MAX14577_IRQ_INT2_CHGDETRUN: |
557 | case MAX14577_IRQ_INT2_DCDTMR: | 562 | case MAX14577_IRQ_INT2_DCDTMR: |
@@ -559,8 +564,62 @@ static irqreturn_t max14577_muic_irq_handler(int irq, void *data) | |||
559 | case MAX14577_IRQ_INT2_VBVOLT: | 564 | case MAX14577_IRQ_INT2_VBVOLT: |
560 | /* Handle charger accessory */ | 565 | /* Handle charger accessory */ |
561 | info->irq_chg = true; | 566 | info->irq_chg = true; |
567 | return 1; | ||
568 | default: | ||
569 | return 0; | ||
570 | } | ||
571 | } | ||
572 | |||
573 | /* | ||
574 | * Sets irq_adc or irq_chg in max14577_muic_info and returns 1. | ||
575 | * Returns 0 if irq_type does not match registered IRQ for this device type. | ||
576 | */ | ||
577 | static int max77836_parse_irq(struct max14577_muic_info *info, int irq_type) | ||
578 | { | ||
579 | /* First check common max14577 interrupts */ | ||
580 | if (max14577_parse_irq(info, irq_type)) | ||
581 | return 1; | ||
582 | |||
583 | switch (irq_type) { | ||
584 | case MAX77836_IRQ_INT1_ADC1K: | ||
585 | info->irq_adc = true; | ||
586 | return 1; | ||
587 | case MAX77836_IRQ_INT2_VIDRM: | ||
588 | /* Handle charger accessory */ | ||
589 | info->irq_chg = true; | ||
590 | return 1; | ||
591 | default: | ||
592 | return 0; | ||
593 | } | ||
594 | } | ||
595 | |||
596 | static irqreturn_t max14577_muic_irq_handler(int irq, void *data) | ||
597 | { | ||
598 | struct max14577_muic_info *info = data; | ||
599 | int i, irq_type = -1; | ||
600 | bool irq_parsed; | ||
601 | |||
602 | /* | ||
603 | * We may be called multiple times for different nested IRQ-s. | ||
604 | * Including changes in INT1_ADC and INT2_CGHTYP at once. | ||
605 | * However we only need to know whether it was ADC, charger | ||
606 | * or both interrupts so decode IRQ and turn on proper flags. | ||
607 | */ | ||
608 | for (i = 0; i < info->muic_irqs_num; i++) | ||
609 | if (irq == info->muic_irqs[i].virq) | ||
610 | irq_type = info->muic_irqs[i].irq; | ||
611 | |||
612 | switch (info->max14577->dev_type) { | ||
613 | case MAXIM_DEVICE_TYPE_MAX77836: | ||
614 | irq_parsed = max77836_parse_irq(info, irq_type); | ||
562 | break; | 615 | break; |
616 | case MAXIM_DEVICE_TYPE_MAX14577: | ||
563 | default: | 617 | default: |
618 | irq_parsed = max14577_parse_irq(info, irq_type); | ||
619 | break; | ||
620 | } | ||
621 | |||
622 | if (!irq_parsed) { | ||
564 | dev_err(info->dev, "muic interrupt: irq %d occurred, skipped\n", | 623 | dev_err(info->dev, "muic interrupt: irq %d occurred, skipped\n", |
565 | irq_type); | 624 | irq_type); |
566 | return IRQ_HANDLED; | 625 | return IRQ_HANDLED; |
@@ -646,6 +705,10 @@ static int max14577_muic_probe(struct platform_device *pdev) | |||
646 | INIT_WORK(&info->irq_work, max14577_muic_irq_work); | 705 | INIT_WORK(&info->irq_work, max14577_muic_irq_work); |
647 | 706 | ||
648 | switch (max14577->dev_type) { | 707 | switch (max14577->dev_type) { |
708 | case MAXIM_DEVICE_TYPE_MAX77836: | ||
709 | info->muic_irqs = max77836_muic_irqs; | ||
710 | info->muic_irqs_num = ARRAY_SIZE(max77836_muic_irqs); | ||
711 | break; | ||
649 | case MAXIM_DEVICE_TYPE_MAX14577: | 712 | case MAXIM_DEVICE_TYPE_MAX14577: |
650 | default: | 713 | default: |
651 | info->muic_irqs = max14577_muic_irqs; | 714 | info->muic_irqs = max14577_muic_irqs; |
@@ -744,6 +807,13 @@ static int max14577_muic_remove(struct platform_device *pdev) | |||
744 | return 0; | 807 | return 0; |
745 | } | 808 | } |
746 | 809 | ||
810 | static const struct platform_device_id max14577_muic_id[] = { | ||
811 | { "max14577-muic", MAXIM_DEVICE_TYPE_MAX14577, }, | ||
812 | { "max77836-muic", MAXIM_DEVICE_TYPE_MAX77836, }, | ||
813 | { } | ||
814 | }; | ||
815 | MODULE_DEVICE_TABLE(platform, max14577_muic_id); | ||
816 | |||
747 | static struct platform_driver max14577_muic_driver = { | 817 | static struct platform_driver max14577_muic_driver = { |
748 | .driver = { | 818 | .driver = { |
749 | .name = "max14577-muic", | 819 | .name = "max14577-muic", |
@@ -751,11 +821,12 @@ static struct platform_driver max14577_muic_driver = { | |||
751 | }, | 821 | }, |
752 | .probe = max14577_muic_probe, | 822 | .probe = max14577_muic_probe, |
753 | .remove = max14577_muic_remove, | 823 | .remove = max14577_muic_remove, |
824 | .id_table = max14577_muic_id, | ||
754 | }; | 825 | }; |
755 | 826 | ||
756 | module_platform_driver(max14577_muic_driver); | 827 | module_platform_driver(max14577_muic_driver); |
757 | 828 | ||
758 | MODULE_DESCRIPTION("MAXIM 14577 Extcon driver"); | 829 | MODULE_DESCRIPTION("Maxim 14577/77836 Extcon driver"); |
759 | MODULE_AUTHOR("Chanwoo Choi <cw00.choi@samsung.com>"); | 830 | MODULE_AUTHOR("Chanwoo Choi <cw00.choi@samsung.com>, Krzysztof Kozlowski <k.kozlowski@samsung.com>"); |
760 | MODULE_LICENSE("GPL"); | 831 | MODULE_LICENSE("GPL"); |
761 | MODULE_ALIAS("platform:extcon-max14577"); | 832 | MODULE_ALIAS("platform:extcon-max14577"); |
diff --git a/drivers/mfd/max14577.c b/drivers/mfd/max14577.c index 20e3b2d81bf0..484d372a4892 100644 --- a/drivers/mfd/max14577.c +++ b/drivers/mfd/max14577.c | |||
@@ -147,6 +147,7 @@ static const struct regmap_irq max77836_muic_irqs[] = { | |||
147 | { .reg_offset = 0, .mask = MAX14577_INT1_ADC_MASK, }, | 147 | { .reg_offset = 0, .mask = MAX14577_INT1_ADC_MASK, }, |
148 | { .reg_offset = 0, .mask = MAX14577_INT1_ADCLOW_MASK, }, | 148 | { .reg_offset = 0, .mask = MAX14577_INT1_ADCLOW_MASK, }, |
149 | { .reg_offset = 0, .mask = MAX14577_INT1_ADCERR_MASK, }, | 149 | { .reg_offset = 0, .mask = MAX14577_INT1_ADCERR_MASK, }, |
150 | { .reg_offset = 0, .mask = MAX77836_INT1_ADC1K_MASK, }, | ||
150 | /* INT2 interrupts */ | 151 | /* INT2 interrupts */ |
151 | { .reg_offset = 1, .mask = MAX14577_INT2_CHGTYP_MASK, }, | 152 | { .reg_offset = 1, .mask = MAX14577_INT2_CHGTYP_MASK, }, |
152 | { .reg_offset = 1, .mask = MAX14577_INT2_CHGDETRUN_MASK, }, | 153 | { .reg_offset = 1, .mask = MAX14577_INT2_CHGDETRUN_MASK, }, |
diff --git a/include/linux/mfd/max14577-private.h b/include/linux/mfd/max14577-private.h index e301bd19b067..a557ae27d8a8 100644 --- a/include/linux/mfd/max14577-private.h +++ b/include/linux/mfd/max14577-private.h | |||
@@ -87,6 +87,7 @@ enum max14577_muic_charger_type { | |||
87 | #define MAX14577_INT1_ADC_MASK BIT(0) | 87 | #define MAX14577_INT1_ADC_MASK BIT(0) |
88 | #define MAX14577_INT1_ADCLOW_MASK BIT(1) | 88 | #define MAX14577_INT1_ADCLOW_MASK BIT(1) |
89 | #define MAX14577_INT1_ADCERR_MASK BIT(2) | 89 | #define MAX14577_INT1_ADCERR_MASK BIT(2) |
90 | #define MAX77836_INT1_ADC1K_MASK BIT(3) | ||
90 | 91 | ||
91 | #define MAX14577_INT2_CHGTYP_MASK BIT(0) | 92 | #define MAX14577_INT2_CHGTYP_MASK BIT(0) |
92 | #define MAX14577_INT2_CHGDETRUN_MASK BIT(1) | 93 | #define MAX14577_INT2_CHGDETRUN_MASK BIT(1) |
@@ -332,6 +333,7 @@ enum max14577_irq { | |||
332 | MAX14577_IRQ_INT1_ADC, | 333 | MAX14577_IRQ_INT1_ADC, |
333 | MAX14577_IRQ_INT1_ADCLOW, | 334 | MAX14577_IRQ_INT1_ADCLOW, |
334 | MAX14577_IRQ_INT1_ADCERR, | 335 | MAX14577_IRQ_INT1_ADCERR, |
336 | MAX77836_IRQ_INT1_ADC1K, | ||
335 | 337 | ||
336 | /* INT2 */ | 338 | /* INT2 */ |
337 | MAX14577_IRQ_INT2_CHGTYP, | 339 | MAX14577_IRQ_INT2_CHGTYP, |
@@ -339,6 +341,7 @@ enum max14577_irq { | |||
339 | MAX14577_IRQ_INT2_DCDTMR, | 341 | MAX14577_IRQ_INT2_DCDTMR, |
340 | MAX14577_IRQ_INT2_DBCHG, | 342 | MAX14577_IRQ_INT2_DBCHG, |
341 | MAX14577_IRQ_INT2_VBVOLT, | 343 | MAX14577_IRQ_INT2_VBVOLT, |
344 | MAX77836_IRQ_INT2_VIDRM, | ||
342 | 345 | ||
343 | /* INT3 */ | 346 | /* INT3 */ |
344 | MAX14577_IRQ_INT3_EOC, | 347 | MAX14577_IRQ_INT3_EOC, |