aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/extcon
diff options
context:
space:
mode:
authorChanwoo Choi <cw00.choi@samsung.com>2014-04-24 04:21:58 -0400
committerChanwoo Choi <cw00.choi@samsung.com>2014-04-24 04:21:58 -0400
commita55d952a2b732e8aaa218a0507935a1deb0c8eea (patch)
tree08cae6fe241a51389ea3a91f27f48ab160aaa221 /drivers/extcon
parentbf9509e032076dc5850598814c243c45a8b81690 (diff)
parent8a82b408acad29161c43072727151d373e68116a (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/Kconfig4
-rw-r--r--drivers/extcon/extcon-max14577.c174
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
30config EXTCON_MAX14577 30config 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
40config EXTCON_MAX77693 40config 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
30enum max14577_muic_adc_debounce_time { 30enum 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 */
49struct max14577_muic_irq {
50 unsigned int irq;
51 const char *name;
52 unsigned int virq;
53};
54
55static 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
66static 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
43struct max14577_muic_info { 79struct 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 */
83struct max14577_muic_irq {
84 unsigned int irq;
85 const char *name;
86 unsigned int virq;
87};
88
89static 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 */
101enum max14577_muic_acc_type { 116enum 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
531static 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 */
550static 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 */
577static 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
596static 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
810static const struct platform_device_id max14577_muic_id[] = {
811 { "max14577-muic", MAXIM_DEVICE_TYPE_MAX14577, },
812 { "max77836-muic", MAXIM_DEVICE_TYPE_MAX77836, },
813 { }
814};
815MODULE_DEVICE_TABLE(platform, max14577_muic_id);
816
738static struct platform_driver max14577_muic_driver = { 817static 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
747module_platform_driver(max14577_muic_driver); 827module_platform_driver(max14577_muic_driver);
748 828
749MODULE_DESCRIPTION("MAXIM 14577 Extcon driver"); 829MODULE_DESCRIPTION("Maxim 14577/77836 Extcon driver");
750MODULE_AUTHOR("Chanwoo Choi <cw00.choi@samsung.com>"); 830MODULE_AUTHOR("Chanwoo Choi <cw00.choi@samsung.com>, Krzysztof Kozlowski <k.kozlowski@samsung.com>");
751MODULE_LICENSE("GPL"); 831MODULE_LICENSE("GPL");
752MODULE_ALIAS("platform:extcon-max14577"); 832MODULE_ALIAS("platform:extcon-max14577");