aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKrzysztof Kozlowski <k.kozlowski@samsung.com>2014-04-14 05:17:19 -0400
committerLee Jones <lee.jones@linaro.org>2014-04-23 09:09:25 -0400
commit4706a5253bcc502a5889feb98392ea7b15dd936e (patch)
treecced4579e808011105fe7c04177d0fffe3e83f66
parentaee2a57c7482c712052b877218aa2c5bc0fe8626 (diff)
extcon: max14577: Add support for MAX77836
Add support for MAX77836 chipset to the max14577 extcon driver. The MAX77836 MUIC has additional interrupts (VIDRM, ADC1K) so IRQ handling is split up into two functions: max14577_parse_irq() and max77836_parse_irq(). Signed-off-by: Krzysztof Kozlowski <k.kozlowski@samsung.com> Acked-by: Chanwoo Choi <cw00.choi@samsung.com> Tested-by: Chanwoo Choi <cw00.choi@samsung.com> Signed-off-by: Lee Jones <lee.jones@linaro.org>
-rw-r--r--drivers/extcon/Kconfig4
-rw-r--r--drivers/extcon/extcon-max14577.c109
-rw-r--r--drivers/mfd/max14577.c1
-rw-r--r--include/linux/mfd/max14577-private.h3
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
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 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
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
65struct max14577_muic_info { 79struct 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
532static 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)
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 */
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);
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
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
747static struct platform_driver max14577_muic_driver = { 817static 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
756module_platform_driver(max14577_muic_driver); 827module_platform_driver(max14577_muic_driver);
757 828
758MODULE_DESCRIPTION("MAXIM 14577 Extcon driver"); 829MODULE_DESCRIPTION("Maxim 14577/77836 Extcon driver");
759MODULE_AUTHOR("Chanwoo Choi <cw00.choi@samsung.com>"); 830MODULE_AUTHOR("Chanwoo Choi <cw00.choi@samsung.com>, Krzysztof Kozlowski <k.kozlowski@samsung.com>");
760MODULE_LICENSE("GPL"); 831MODULE_LICENSE("GPL");
761MODULE_ALIAS("platform:extcon-max14577"); 832MODULE_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,