diff options
author | Chanwoo Choi <cw00.choi@samsung.com> | 2014-04-24 04:21:58 -0400 |
---|---|---|
committer | Chanwoo Choi <cw00.choi@samsung.com> | 2014-04-24 04:21:58 -0400 |
commit | a55d952a2b732e8aaa218a0507935a1deb0c8eea (patch) | |
tree | 08cae6fe241a51389ea3a91f27f48ab160aaa221 /drivers/extcon | |
parent | bf9509e032076dc5850598814c243c45a8b81690 (diff) | |
parent | 8a82b408acad29161c43072727151d373e68116a (diff) |
Merge tag 'ib-mfd-extcon-3.16' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd into HEAD
Immutable branch between MFD and Extcon due for v3.16 merge-window.
Diffstat (limited to 'drivers/extcon')
-rw-r--r-- | drivers/extcon/Kconfig | 4 | ||||
-rw-r--r-- | drivers/extcon/extcon-max14577.c | 174 |
2 files changed, 129 insertions, 49 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 3846941801b8..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 |
@@ -24,7 +25,6 @@ | |||
24 | #include <linux/mfd/max14577-private.h> | 25 | #include <linux/mfd/max14577-private.h> |
25 | #include <linux/extcon.h> | 26 | #include <linux/extcon.h> |
26 | 27 | ||
27 | #define DEV_NAME "max14577-muic" | ||
28 | #define DELAY_MS_DEFAULT 17000 /* unit: millisecond */ | 28 | #define DELAY_MS_DEFAULT 17000 /* unit: millisecond */ |
29 | 29 | ||
30 | enum max14577_muic_adc_debounce_time { | 30 | enum max14577_muic_adc_debounce_time { |
@@ -40,6 +40,42 @@ enum max14577_muic_status { | |||
40 | MAX14577_MUIC_STATUS_END, | 40 | MAX14577_MUIC_STATUS_END, |
41 | }; | 41 | }; |
42 | 42 | ||
43 | /** | ||
44 | * struct max14577_muic_irq | ||
45 | * @irq: the index of irq list of MUIC device. | ||
46 | * @name: the name of irq. | ||
47 | * @virq: the virtual irq to use irq domain | ||
48 | */ | ||
49 | struct max14577_muic_irq { | ||
50 | unsigned int irq; | ||
51 | const char *name; | ||
52 | unsigned int virq; | ||
53 | }; | ||
54 | |||
55 | static struct max14577_muic_irq max14577_muic_irqs[] = { | ||
56 | { MAX14577_IRQ_INT1_ADC, "muic-ADC" }, | ||
57 | { MAX14577_IRQ_INT1_ADCLOW, "muic-ADCLOW" }, | ||
58 | { MAX14577_IRQ_INT1_ADCERR, "muic-ADCError" }, | ||
59 | { MAX14577_IRQ_INT2_CHGTYP, "muic-CHGTYP" }, | ||
60 | { MAX14577_IRQ_INT2_CHGDETRUN, "muic-CHGDETRUN" }, | ||
61 | { MAX14577_IRQ_INT2_DCDTMR, "muic-DCDTMR" }, | ||
62 | { MAX14577_IRQ_INT2_DBCHG, "muic-DBCHG" }, | ||
63 | { MAX14577_IRQ_INT2_VBVOLT, "muic-VBVOLT" }, | ||
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 | |||
43 | struct max14577_muic_info { | 79 | struct max14577_muic_info { |
44 | struct device *dev; | 80 | struct device *dev; |
45 | struct max14577 *max14577; | 81 | struct max14577 *max14577; |
@@ -48,6 +84,8 @@ struct max14577_muic_info { | |||
48 | int prev_chg_type; | 84 | int prev_chg_type; |
49 | u8 status[MAX14577_MUIC_STATUS_END]; | 85 | u8 status[MAX14577_MUIC_STATUS_END]; |
50 | 86 | ||
87 | struct max14577_muic_irq *muic_irqs; | ||
88 | unsigned int muic_irqs_num; | ||
51 | bool irq_adc; | 89 | bool irq_adc; |
52 | bool irq_chg; | 90 | bool irq_chg; |
53 | struct work_struct irq_work; | 91 | struct work_struct irq_work; |
@@ -74,29 +112,6 @@ enum max14577_muic_cable_group { | |||
74 | MAX14577_CABLE_GROUP_CHG, | 112 | MAX14577_CABLE_GROUP_CHG, |
75 | }; | 113 | }; |
76 | 114 | ||
77 | /** | ||
78 | * struct max14577_muic_irq | ||
79 | * @irq: the index of irq list of MUIC device. | ||
80 | * @name: the name of irq. | ||
81 | * @virq: the virtual irq to use irq domain | ||
82 | */ | ||
83 | struct max14577_muic_irq { | ||
84 | unsigned int irq; | ||
85 | const char *name; | ||
86 | unsigned int virq; | ||
87 | }; | ||
88 | |||
89 | static struct max14577_muic_irq muic_irqs[] = { | ||
90 | { MAX14577_IRQ_INT1_ADC, "muic-ADC" }, | ||
91 | { MAX14577_IRQ_INT1_ADCLOW, "muic-ADCLOW" }, | ||
92 | { MAX14577_IRQ_INT1_ADCERR, "muic-ADCError" }, | ||
93 | { MAX14577_IRQ_INT2_CHGTYP, "muic-CHGTYP" }, | ||
94 | { MAX14577_IRQ_INT2_CHGDETRUN, "muic-CHGDETRUN" }, | ||
95 | { MAX14577_IRQ_INT2_DCDTMR, "muic-DCDTMR" }, | ||
96 | { MAX14577_IRQ_INT2_DBCHG, "muic-DBCHG" }, | ||
97 | { MAX14577_IRQ_INT2_VBVOLT, "muic-VBVOLT" }, | ||
98 | }; | ||
99 | |||
100 | /* Define supported accessory type */ | 115 | /* Define supported accessory type */ |
101 | enum max14577_muic_acc_type { | 116 | enum max14577_muic_acc_type { |
102 | MAX14577_MUIC_ADC_GROUND = 0x0, | 117 | MAX14577_MUIC_ADC_GROUND = 0x0, |
@@ -528,21 +543,12 @@ static void max14577_muic_irq_work(struct work_struct *work) | |||
528 | return; | 543 | return; |
529 | } | 544 | } |
530 | 545 | ||
531 | 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) | ||
532 | { | 551 | { |
533 | struct max14577_muic_info *info = data; | ||
534 | int i, irq_type = -1; | ||
535 | |||
536 | /* | ||
537 | * We may be called multiple times for different nested IRQ-s. | ||
538 | * Including changes in INT1_ADC and INT2_CGHTYP at once. | ||
539 | * However we only need to know whether it was ADC, charger | ||
540 | * or both interrupts so decode IRQ and turn on proper flags. | ||
541 | */ | ||
542 | for (i = 0; i < ARRAY_SIZE(muic_irqs); i++) | ||
543 | if (irq == muic_irqs[i].virq) | ||
544 | irq_type = muic_irqs[i].irq; | ||
545 | |||
546 | switch (irq_type) { | 552 | switch (irq_type) { |
547 | case MAX14577_IRQ_INT1_ADC: | 553 | case MAX14577_IRQ_INT1_ADC: |
548 | case MAX14577_IRQ_INT1_ADCLOW: | 554 | case MAX14577_IRQ_INT1_ADCLOW: |
@@ -550,7 +556,7 @@ static irqreturn_t max14577_muic_irq_handler(int irq, void *data) | |||
550 | /* Handle all of accessory except for | 556 | /* Handle all of accessory except for |
551 | type of charger accessory */ | 557 | type of charger accessory */ |
552 | info->irq_adc = true; | 558 | info->irq_adc = true; |
553 | break; | 559 | return 1; |
554 | case MAX14577_IRQ_INT2_CHGTYP: | 560 | case MAX14577_IRQ_INT2_CHGTYP: |
555 | case MAX14577_IRQ_INT2_CHGDETRUN: | 561 | case MAX14577_IRQ_INT2_CHGDETRUN: |
556 | case MAX14577_IRQ_INT2_DCDTMR: | 562 | case MAX14577_IRQ_INT2_DCDTMR: |
@@ -558,8 +564,62 @@ static irqreturn_t max14577_muic_irq_handler(int irq, void *data) | |||
558 | case MAX14577_IRQ_INT2_VBVOLT: | 564 | case MAX14577_IRQ_INT2_VBVOLT: |
559 | /* Handle charger accessory */ | 565 | /* Handle charger accessory */ |
560 | 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); | ||
561 | break; | 615 | break; |
616 | case MAXIM_DEVICE_TYPE_MAX14577: | ||
562 | default: | 617 | default: |
618 | irq_parsed = max14577_parse_irq(info, irq_type); | ||
619 | break; | ||
620 | } | ||
621 | |||
622 | if (!irq_parsed) { | ||
563 | dev_err(info->dev, "muic interrupt: irq %d occurred, skipped\n", | 623 | dev_err(info->dev, "muic interrupt: irq %d occurred, skipped\n", |
564 | irq_type); | 624 | irq_type); |
565 | return IRQ_HANDLED; | 625 | return IRQ_HANDLED; |
@@ -644,9 +704,20 @@ static int max14577_muic_probe(struct platform_device *pdev) | |||
644 | 704 | ||
645 | INIT_WORK(&info->irq_work, max14577_muic_irq_work); | 705 | INIT_WORK(&info->irq_work, max14577_muic_irq_work); |
646 | 706 | ||
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; | ||
712 | case MAXIM_DEVICE_TYPE_MAX14577: | ||
713 | default: | ||
714 | info->muic_irqs = max14577_muic_irqs; | ||
715 | info->muic_irqs_num = ARRAY_SIZE(max14577_muic_irqs); | ||
716 | } | ||
717 | |||
647 | /* Support irq domain for max14577 MUIC device */ | 718 | /* Support irq domain for max14577 MUIC device */ |
648 | for (i = 0; i < ARRAY_SIZE(muic_irqs); i++) { | 719 | for (i = 0; i < info->muic_irqs_num; i++) { |
649 | struct max14577_muic_irq *muic_irq = &muic_irqs[i]; | 720 | struct max14577_muic_irq *muic_irq = &info->muic_irqs[i]; |
650 | unsigned int virq = 0; | 721 | unsigned int virq = 0; |
651 | 722 | ||
652 | virq = regmap_irq_get_virq(max14577->irq_data, muic_irq->irq); | 723 | virq = regmap_irq_get_virq(max14577->irq_data, muic_irq->irq); |
@@ -673,7 +744,8 @@ static int max14577_muic_probe(struct platform_device *pdev) | |||
673 | dev_err(&pdev->dev, "failed to allocate memory for extcon\n"); | 744 | dev_err(&pdev->dev, "failed to allocate memory for extcon\n"); |
674 | return -ENOMEM; | 745 | return -ENOMEM; |
675 | } | 746 | } |
676 | info->edev->name = DEV_NAME; | 747 | |
748 | info->edev->name = dev_name(&pdev->dev); | ||
677 | info->edev->supported_cable = max14577_extcon_cable; | 749 | info->edev->supported_cable = max14577_extcon_cable; |
678 | ret = extcon_dev_register(info->edev); | 750 | ret = extcon_dev_register(info->edev); |
679 | if (ret) { | 751 | if (ret) { |
@@ -735,18 +807,26 @@ static int max14577_muic_remove(struct platform_device *pdev) | |||
735 | return 0; | 807 | return 0; |
736 | } | 808 | } |
737 | 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 | |||
738 | static struct platform_driver max14577_muic_driver = { | 817 | static struct platform_driver max14577_muic_driver = { |
739 | .driver = { | 818 | .driver = { |
740 | .name = DEV_NAME, | 819 | .name = "max14577-muic", |
741 | .owner = THIS_MODULE, | 820 | .owner = THIS_MODULE, |
742 | }, | 821 | }, |
743 | .probe = max14577_muic_probe, | 822 | .probe = max14577_muic_probe, |
744 | .remove = max14577_muic_remove, | 823 | .remove = max14577_muic_remove, |
824 | .id_table = max14577_muic_id, | ||
745 | }; | 825 | }; |
746 | 826 | ||
747 | module_platform_driver(max14577_muic_driver); | 827 | module_platform_driver(max14577_muic_driver); |
748 | 828 | ||
749 | MODULE_DESCRIPTION("MAXIM 14577 Extcon driver"); | 829 | MODULE_DESCRIPTION("Maxim 14577/77836 Extcon driver"); |
750 | MODULE_AUTHOR("Chanwoo Choi <cw00.choi@samsung.com>"); | 830 | MODULE_AUTHOR("Chanwoo Choi <cw00.choi@samsung.com>, Krzysztof Kozlowski <k.kozlowski@samsung.com>"); |
751 | MODULE_LICENSE("GPL"); | 831 | MODULE_LICENSE("GPL"); |
752 | MODULE_ALIAS("platform:extcon-max14577"); | 832 | MODULE_ALIAS("platform:extcon-max14577"); |