aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>2015-04-01 07:51:59 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2015-04-01 07:51:59 -0400
commit86d39839bc6bccc9b6b89de8c9c38beb9709f559 (patch)
tree4b3afdf6e5b497d31b76e3bc8ba747d637b1a63f
parent911a88829725572820dad9a168e735c606a2fdcb (diff)
parent66bee35f29683fc4a9a530a1c56a0ec45e3f7d72 (diff)
Merge tag 'extcon-next-for-4.1' of git://git.kernel.org/pub/scm/linux/kernel/git/chanwoo/extcon into char-misc-next
Chanwoo writes: Update extcon for v4.1 This patchset include two new extcon driver and fix minor issue of extcon driver. Detailed description for patchset: 1. new extcon-max77843.c and extcon-usb-gpio.c extcon driver - extcon-max77843.c driver support the MAXIM MAX77843 MUIC (Micor-USB Interface Controller) device which handles the various external connectors such as TA/USB /USB-HOST/JIG and so on. - extcon-usb-gpio.c driver support the USB and USB-HOST cable detection by using the GPIO pin which is connected to USB ID pin. This GPIO pin updates the USB cable states. 2. Rename the filename of extcon core driver and add missing locking mechanism - Rename the previous extcon-class driver.c as extcon.c because '-class' postfix is not necessary word. - extcon core driver (extcon.c) used the raw_notifier_chain. It must be protected by locking mechanism to avoid the list changing while extcon_update_state() is executed. 3. Fix minor issue of extcon drviers - Fix cable name by using the capital letter instead of small letter on extcon-max77693.c driver. - Clean-up code of extcon-arizona.c to detect headphone cable. - Fix the wrong return type and variable type on extcon-max77843.c. - Fix the checkpatch warning of all extcon drivers.
-rw-r--r--Documentation/devicetree/bindings/extcon/extcon-usb-gpio.txt18
-rw-r--r--drivers/extcon/Kconfig17
-rw-r--r--drivers/extcon/Makefile4
-rw-r--r--drivers/extcon/extcon-arizona.c49
-rw-r--r--drivers/extcon/extcon-max14577.c5
-rw-r--r--drivers/extcon/extcon-max77693.c37
-rw-r--r--drivers/extcon/extcon-max77843.c881
-rw-r--r--drivers/extcon/extcon-max8997.c5
-rw-r--r--drivers/extcon/extcon-rt8973a.c6
-rw-r--r--drivers/extcon/extcon-sm5502.c6
-rw-r--r--drivers/extcon/extcon-usb-gpio.c237
-rw-r--r--drivers/extcon/extcon.c (renamed from drivers/extcon/extcon-class.c)36
-rw-r--r--include/linux/mfd/arizona/core.h2
-rw-r--r--sound/soc/codecs/arizona.c4
14 files changed, 1248 insertions, 59 deletions
diff --git a/Documentation/devicetree/bindings/extcon/extcon-usb-gpio.txt b/Documentation/devicetree/bindings/extcon/extcon-usb-gpio.txt
new file mode 100644
index 000000000000..af0b903de293
--- /dev/null
+++ b/Documentation/devicetree/bindings/extcon/extcon-usb-gpio.txt
@@ -0,0 +1,18 @@
1USB GPIO Extcon device
2
3This is a virtual device used to generate USB cable states from the USB ID pin
4connected to a GPIO pin.
5
6Required properties:
7- compatible: Should be "linux,extcon-usb-gpio"
8- id-gpio: gpio for USB ID pin. See gpio binding.
9
10Example: Examples of extcon-usb-gpio node in dra7-evm.dts as listed below:
11 extcon_usb1 {
12 compatible = "linux,extcon-usb-gpio";
13 id-gpio = <&gpio6 1 GPIO_ACTIVE_HIGH>;
14 }
15
16 &omap_dwc3_1 {
17 extcon = <&extcon_usb1>;
18 };
diff --git a/drivers/extcon/Kconfig b/drivers/extcon/Kconfig
index 6a1f7de6fa54..fdc0bf0543ce 100644
--- a/drivers/extcon/Kconfig
+++ b/drivers/extcon/Kconfig
@@ -55,6 +55,16 @@ config EXTCON_MAX77693
55 Maxim MAX77693 PMIC. The MAX77693 MUIC is a USB port accessory 55 Maxim MAX77693 PMIC. The MAX77693 MUIC is a USB port accessory
56 detector and switch. 56 detector and switch.
57 57
58config EXTCON_MAX77843
59 tristate "MAX77843 EXTCON Support"
60 depends on MFD_MAX77843
61 select IRQ_DOMAIN
62 select REGMAP_I2C
63 help
64 If you say yes here you get support for the MUIC device of
65 Maxim MAX77843. The MAX77843 MUIC is a USB port accessory
66 detector add switch.
67
58config EXTCON_MAX8997 68config EXTCON_MAX8997
59 tristate "MAX8997 EXTCON Support" 69 tristate "MAX8997 EXTCON Support"
60 depends on MFD_MAX8997 && IRQ_DOMAIN 70 depends on MFD_MAX8997 && IRQ_DOMAIN
@@ -93,4 +103,11 @@ config EXTCON_SM5502
93 Silicon Mitus SM5502. The SM5502 is a USB port accessory 103 Silicon Mitus SM5502. The SM5502 is a USB port accessory
94 detector and switch. 104 detector and switch.
95 105
106config EXTCON_USB_GPIO
107 tristate "USB GPIO extcon support"
108 depends on GPIOLIB
109 help
110 Say Y here to enable GPIO based USB cable detection extcon support.
111 Used typically if GPIO is used for USB ID pin detection.
112
96endif # MULTISTATE_SWITCH 113endif # MULTISTATE_SWITCH
diff --git a/drivers/extcon/Makefile b/drivers/extcon/Makefile
index 0370b42e5a27..9204114791a3 100644
--- a/drivers/extcon/Makefile
+++ b/drivers/extcon/Makefile
@@ -2,13 +2,15 @@
2# Makefile for external connector class (extcon) devices 2# Makefile for external connector class (extcon) devices
3# 3#
4 4
5obj-$(CONFIG_EXTCON) += extcon-class.o 5obj-$(CONFIG_EXTCON) += extcon.o
6obj-$(CONFIG_EXTCON_ADC_JACK) += extcon-adc-jack.o 6obj-$(CONFIG_EXTCON_ADC_JACK) += extcon-adc-jack.o
7obj-$(CONFIG_EXTCON_ARIZONA) += extcon-arizona.o 7obj-$(CONFIG_EXTCON_ARIZONA) += extcon-arizona.o
8obj-$(CONFIG_EXTCON_GPIO) += extcon-gpio.o 8obj-$(CONFIG_EXTCON_GPIO) += extcon-gpio.o
9obj-$(CONFIG_EXTCON_MAX14577) += extcon-max14577.o 9obj-$(CONFIG_EXTCON_MAX14577) += extcon-max14577.o
10obj-$(CONFIG_EXTCON_MAX77693) += extcon-max77693.o 10obj-$(CONFIG_EXTCON_MAX77693) += extcon-max77693.o
11obj-$(CONFIG_EXTCON_MAX77843) += extcon-max77843.o
11obj-$(CONFIG_EXTCON_MAX8997) += extcon-max8997.o 12obj-$(CONFIG_EXTCON_MAX8997) += extcon-max8997.o
12obj-$(CONFIG_EXTCON_PALMAS) += extcon-palmas.o 13obj-$(CONFIG_EXTCON_PALMAS) += extcon-palmas.o
13obj-$(CONFIG_EXTCON_RT8973A) += extcon-rt8973a.o 14obj-$(CONFIG_EXTCON_RT8973A) += extcon-rt8973a.o
14obj-$(CONFIG_EXTCON_SM5502) += extcon-sm5502.o 15obj-$(CONFIG_EXTCON_SM5502) += extcon-sm5502.o
16obj-$(CONFIG_EXTCON_USB_GPIO) += extcon-usb-gpio.o
diff --git a/drivers/extcon/extcon-arizona.c b/drivers/extcon/extcon-arizona.c
index 63f01c42aed4..d9e763cddb50 100644
--- a/drivers/extcon/extcon-arizona.c
+++ b/drivers/extcon/extcon-arizona.c
@@ -136,18 +136,35 @@ static const char *arizona_cable[] = {
136 136
137static void arizona_start_hpdet_acc_id(struct arizona_extcon_info *info); 137static void arizona_start_hpdet_acc_id(struct arizona_extcon_info *info);
138 138
139static void arizona_extcon_do_magic(struct arizona_extcon_info *info, 139static void arizona_extcon_hp_clamp(struct arizona_extcon_info *info,
140 unsigned int magic) 140 bool clamp)
141{ 141{
142 struct arizona *arizona = info->arizona; 142 struct arizona *arizona = info->arizona;
143 unsigned int mask = 0, val = 0;
143 int ret; 144 int ret;
144 145
146 switch (arizona->type) {
147 case WM5110:
148 mask = ARIZONA_HP1L_SHRTO | ARIZONA_HP1L_FLWR |
149 ARIZONA_HP1L_SHRTI;
150 if (clamp)
151 val = ARIZONA_HP1L_SHRTO;
152 else
153 val = ARIZONA_HP1L_FLWR | ARIZONA_HP1L_SHRTI;
154 break;
155 default:
156 mask = ARIZONA_RMV_SHRT_HP1L;
157 if (clamp)
158 val = ARIZONA_RMV_SHRT_HP1L;
159 break;
160 };
161
145 mutex_lock(&arizona->dapm->card->dapm_mutex); 162 mutex_lock(&arizona->dapm->card->dapm_mutex);
146 163
147 arizona->hpdet_magic = magic; 164 arizona->hpdet_clamp = clamp;
148 165
149 /* Keep the HP output stages disabled while doing the magic */ 166 /* Keep the HP output stages disabled while doing the clamp */
150 if (magic) { 167 if (clamp) {
151 ret = regmap_update_bits(arizona->regmap, 168 ret = regmap_update_bits(arizona->regmap,
152 ARIZONA_OUTPUT_ENABLES_1, 169 ARIZONA_OUTPUT_ENABLES_1,
153 ARIZONA_OUT1L_ENA | 170 ARIZONA_OUT1L_ENA |
@@ -158,20 +175,20 @@ static void arizona_extcon_do_magic(struct arizona_extcon_info *info,
158 ret); 175 ret);
159 } 176 }
160 177
161 ret = regmap_update_bits(arizona->regmap, 0x225, 0x4000, 178 ret = regmap_update_bits(arizona->regmap, ARIZONA_HP_CTRL_1L,
162 magic); 179 mask, val);
163 if (ret != 0) 180 if (ret != 0)
164 dev_warn(arizona->dev, "Failed to do magic: %d\n", 181 dev_warn(arizona->dev, "Failed to do clamp: %d\n",
165 ret); 182 ret);
166 183
167 ret = regmap_update_bits(arizona->regmap, 0x226, 0x4000, 184 ret = regmap_update_bits(arizona->regmap, ARIZONA_HP_CTRL_1R,
168 magic); 185 mask, val);
169 if (ret != 0) 186 if (ret != 0)
170 dev_warn(arizona->dev, "Failed to do magic: %d\n", 187 dev_warn(arizona->dev, "Failed to do clamp: %d\n",
171 ret); 188 ret);
172 189
173 /* Restore the desired state while not doing the magic */ 190 /* Restore the desired state while not doing the clamp */
174 if (!magic) { 191 if (!clamp) {
175 ret = regmap_update_bits(arizona->regmap, 192 ret = regmap_update_bits(arizona->regmap,
176 ARIZONA_OUTPUT_ENABLES_1, 193 ARIZONA_OUTPUT_ENABLES_1,
177 ARIZONA_OUT1L_ENA | 194 ARIZONA_OUT1L_ENA |
@@ -603,7 +620,7 @@ done:
603 ARIZONA_HP_IMPEDANCE_RANGE_MASK | ARIZONA_HP_POLL, 620 ARIZONA_HP_IMPEDANCE_RANGE_MASK | ARIZONA_HP_POLL,
604 0); 621 0);
605 622
606 arizona_extcon_do_magic(info, 0); 623 arizona_extcon_hp_clamp(info, false);
607 624
608 if (id_gpio) 625 if (id_gpio)
609 gpio_set_value_cansleep(id_gpio, 0); 626 gpio_set_value_cansleep(id_gpio, 0);
@@ -648,7 +665,7 @@ static void arizona_identify_headphone(struct arizona_extcon_info *info)
648 if (info->mic) 665 if (info->mic)
649 arizona_stop_mic(info); 666 arizona_stop_mic(info);
650 667
651 arizona_extcon_do_magic(info, 0x4000); 668 arizona_extcon_hp_clamp(info, true);
652 669
653 ret = regmap_update_bits(arizona->regmap, 670 ret = regmap_update_bits(arizona->regmap,
654 ARIZONA_ACCESSORY_DETECT_MODE_1, 671 ARIZONA_ACCESSORY_DETECT_MODE_1,
@@ -699,7 +716,7 @@ static void arizona_start_hpdet_acc_id(struct arizona_extcon_info *info)
699 716
700 info->hpdet_active = true; 717 info->hpdet_active = true;
701 718
702 arizona_extcon_do_magic(info, 0x4000); 719 arizona_extcon_hp_clamp(info, true);
703 720
704 ret = regmap_update_bits(arizona->regmap, 721 ret = regmap_update_bits(arizona->regmap,
705 ARIZONA_ACCESSORY_DETECT_MODE_1, 722 ARIZONA_ACCESSORY_DETECT_MODE_1,
diff --git a/drivers/extcon/extcon-max14577.c b/drivers/extcon/extcon-max14577.c
index c1bf0cf747b0..3823aa4a3a80 100644
--- a/drivers/extcon/extcon-max14577.c
+++ b/drivers/extcon/extcon-max14577.c
@@ -539,8 +539,6 @@ static void max14577_muic_irq_work(struct work_struct *work)
539 dev_err(info->dev, "failed to handle MUIC interrupt\n"); 539 dev_err(info->dev, "failed to handle MUIC interrupt\n");
540 540
541 mutex_unlock(&info->mutex); 541 mutex_unlock(&info->mutex);
542
543 return;
544} 542}
545 543
546/* 544/*
@@ -730,8 +728,7 @@ static int max14577_muic_probe(struct platform_device *pdev)
730 muic_irq->name, info); 728 muic_irq->name, info);
731 if (ret) { 729 if (ret) {
732 dev_err(&pdev->dev, 730 dev_err(&pdev->dev,
733 "failed: irq request (IRQ: %d," 731 "failed: irq request (IRQ: %d, error :%d)\n",
734 " error :%d)\n",
735 muic_irq->irq, ret); 732 muic_irq->irq, ret);
736 return ret; 733 return ret;
737 } 734 }
diff --git a/drivers/extcon/extcon-max77693.c b/drivers/extcon/extcon-max77693.c
index af165fd0c6f5..a66bec8f6252 100644
--- a/drivers/extcon/extcon-max77693.c
+++ b/drivers/extcon/extcon-max77693.c
@@ -190,8 +190,8 @@ enum max77693_muic_acc_type {
190 /* The below accessories have same ADC value so ADCLow and 190 /* The below accessories have same ADC value so ADCLow and
191 ADC1K bit is used to separate specific accessory */ 191 ADC1K bit is used to separate specific accessory */
192 /* ADC|VBVolot|ADCLow|ADC1K| */ 192 /* ADC|VBVolot|ADCLow|ADC1K| */
193 MAX77693_MUIC_GND_USB_OTG = 0x100, /* 0x0| 0| 0| 0| */ 193 MAX77693_MUIC_GND_USB_HOST = 0x100, /* 0x0| 0| 0| 0| */
194 MAX77693_MUIC_GND_USB_OTG_VB = 0x104, /* 0x0| 1| 0| 0| */ 194 MAX77693_MUIC_GND_USB_HOST_VB = 0x104, /* 0x0| 1| 0| 0| */
195 MAX77693_MUIC_GND_AV_CABLE_LOAD = 0x102,/* 0x0| 0| 1| 0| */ 195 MAX77693_MUIC_GND_AV_CABLE_LOAD = 0x102,/* 0x0| 0| 1| 0| */
196 MAX77693_MUIC_GND_MHL = 0x103, /* 0x0| 0| 1| 1| */ 196 MAX77693_MUIC_GND_MHL = 0x103, /* 0x0| 0| 1| 1| */
197 MAX77693_MUIC_GND_MHL_VB = 0x107, /* 0x0| 1| 1| 1| */ 197 MAX77693_MUIC_GND_MHL_VB = 0x107, /* 0x0| 1| 1| 1| */
@@ -228,7 +228,7 @@ static const char *max77693_extcon_cable[] = {
228 [EXTCON_CABLE_SLOW_CHARGER] = "Slow-charger", 228 [EXTCON_CABLE_SLOW_CHARGER] = "Slow-charger",
229 [EXTCON_CABLE_CHARGE_DOWNSTREAM] = "Charge-downstream", 229 [EXTCON_CABLE_CHARGE_DOWNSTREAM] = "Charge-downstream",
230 [EXTCON_CABLE_MHL] = "MHL", 230 [EXTCON_CABLE_MHL] = "MHL",
231 [EXTCON_CABLE_MHL_TA] = "MHL_TA", 231 [EXTCON_CABLE_MHL_TA] = "MHL-TA",
232 [EXTCON_CABLE_JIG_USB_ON] = "JIG-USB-ON", 232 [EXTCON_CABLE_JIG_USB_ON] = "JIG-USB-ON",
233 [EXTCON_CABLE_JIG_USB_OFF] = "JIG-USB-OFF", 233 [EXTCON_CABLE_JIG_USB_OFF] = "JIG-USB-OFF",
234 [EXTCON_CABLE_JIG_UART_OFF] = "JIG-UART-OFF", 234 [EXTCON_CABLE_JIG_UART_OFF] = "JIG-UART-OFF",
@@ -403,8 +403,8 @@ static int max77693_muic_get_cable_type(struct max77693_muic_info *info,
403 403
404 /** 404 /**
405 * [0x1|VBVolt|ADCLow|ADC1K] 405 * [0x1|VBVolt|ADCLow|ADC1K]
406 * [0x1| 0| 0| 0] USB_OTG 406 * [0x1| 0| 0| 0] USB_HOST
407 * [0x1| 1| 0| 0] USB_OTG_VB 407 * [0x1| 1| 0| 0] USB_HSOT_VB
408 * [0x1| 0| 1| 0] Audio Video cable with load 408 * [0x1| 0| 1| 0] Audio Video cable with load
409 * [0x1| 0| 1| 1] MHL without charging cable 409 * [0x1| 0| 1| 1] MHL without charging cable
410 * [0x1| 1| 1| 1] MHL with charging cable 410 * [0x1| 1| 1| 1] MHL with charging cable
@@ -523,7 +523,7 @@ static int max77693_muic_dock_handler(struct max77693_muic_info *info,
523 * - Support charging and data connection through micro-usb port 523 * - Support charging and data connection through micro-usb port
524 * if USB cable is connected between target and host 524 * if USB cable is connected between target and host
525 * device. 525 * device.
526 * - Support OTG device (Mouse/Keyboard) 526 * - Support OTG(On-The-Go) device (Ex: Mouse/Keyboard)
527 */ 527 */
528 ret = max77693_muic_set_path(info, info->path_usb, attached); 528 ret = max77693_muic_set_path(info, info->path_usb, attached);
529 if (ret < 0) 529 if (ret < 0)
@@ -609,9 +609,9 @@ static int max77693_muic_adc_ground_handler(struct max77693_muic_info *info)
609 MAX77693_CABLE_GROUP_ADC_GND, &attached); 609 MAX77693_CABLE_GROUP_ADC_GND, &attached);
610 610
611 switch (cable_type_gnd) { 611 switch (cable_type_gnd) {
612 case MAX77693_MUIC_GND_USB_OTG: 612 case MAX77693_MUIC_GND_USB_HOST:
613 case MAX77693_MUIC_GND_USB_OTG_VB: 613 case MAX77693_MUIC_GND_USB_HOST_VB:
614 /* USB_OTG, PATH: AP_USB */ 614 /* USB_HOST, PATH: AP_USB */
615 ret = max77693_muic_set_path(info, CONTROL1_SW_USB, attached); 615 ret = max77693_muic_set_path(info, CONTROL1_SW_USB, attached);
616 if (ret < 0) 616 if (ret < 0)
617 return ret; 617 return ret;
@@ -704,7 +704,7 @@ static int max77693_muic_adc_handler(struct max77693_muic_info *info)
704 704
705 switch (cable_type) { 705 switch (cable_type) {
706 case MAX77693_MUIC_ADC_GROUND: 706 case MAX77693_MUIC_ADC_GROUND:
707 /* USB_OTG/MHL/Audio */ 707 /* USB_HOST/MHL/Audio */
708 max77693_muic_adc_ground_handler(info); 708 max77693_muic_adc_ground_handler(info);
709 break; 709 break;
710 case MAX77693_MUIC_ADC_FACTORY_MODE_USB_OFF: 710 case MAX77693_MUIC_ADC_FACTORY_MODE_USB_OFF:
@@ -823,19 +823,19 @@ static int max77693_muic_chg_handler(struct max77693_muic_info *info)
823 case MAX77693_MUIC_GND_MHL: 823 case MAX77693_MUIC_GND_MHL:
824 case MAX77693_MUIC_GND_MHL_VB: 824 case MAX77693_MUIC_GND_MHL_VB:
825 /* 825 /*
826 * MHL cable with MHL_TA(USB/TA) cable 826 * MHL cable with MHL-TA(USB/TA) cable
827 * - MHL cable include two port(HDMI line and separate 827 * - MHL cable include two port(HDMI line and separate
828 * micro-usb port. When the target connect MHL cable, 828 * micro-usb port. When the target connect MHL cable,
829 * extcon driver check whether MHL_TA(USB/TA) cable is 829 * extcon driver check whether MHL-TA(USB/TA) cable is
830 * connected. If MHL_TA cable is connected, extcon 830 * connected. If MHL-TA cable is connected, extcon
831 * driver notify state to notifiee for charging battery. 831 * driver notify state to notifiee for charging battery.
832 * 832 *
833 * Features of 'MHL_TA(USB/TA) with MHL cable' 833 * Features of 'MHL-TA(USB/TA) with MHL cable'
834 * - Support MHL 834 * - Support MHL
835 * - Support charging through micro-usb port without 835 * - Support charging through micro-usb port without
836 * data connection 836 * data connection
837 */ 837 */
838 extcon_set_cable_state(info->edev, "MHL_TA", attached); 838 extcon_set_cable_state(info->edev, "MHL-TA", attached);
839 if (!cable_attached) 839 if (!cable_attached)
840 extcon_set_cable_state(info->edev, 840 extcon_set_cable_state(info->edev,
841 "MHL", cable_attached); 841 "MHL", cable_attached);
@@ -886,7 +886,7 @@ static int max77693_muic_chg_handler(struct max77693_muic_info *info)
886 * - Support charging and data connection through micro- 886 * - Support charging and data connection through micro-
887 * usb port if USB cable is connected between target 887 * usb port if USB cable is connected between target
888 * and host device 888 * and host device
889 * - Support OTG device (Mouse/Keyboard) 889 * - Support OTG(On-The-Go) device (Ex: Mouse/Keyboard)
890 */ 890 */
891 ret = max77693_muic_set_path(info, info->path_usb, 891 ret = max77693_muic_set_path(info, info->path_usb,
892 attached); 892 attached);
@@ -1019,8 +1019,6 @@ static void max77693_muic_irq_work(struct work_struct *work)
1019 dev_err(info->dev, "failed to handle MUIC interrupt\n"); 1019 dev_err(info->dev, "failed to handle MUIC interrupt\n");
1020 1020
1021 mutex_unlock(&info->mutex); 1021 mutex_unlock(&info->mutex);
1022
1023 return;
1024} 1022}
1025 1023
1026static irqreturn_t max77693_muic_irq_handler(int irq, void *data) 1024static irqreturn_t max77693_muic_irq_handler(int irq, void *data)
@@ -1171,8 +1169,7 @@ static int max77693_muic_probe(struct platform_device *pdev)
1171 muic_irq->name, info); 1169 muic_irq->name, info);
1172 if (ret) { 1170 if (ret) {
1173 dev_err(&pdev->dev, 1171 dev_err(&pdev->dev,
1174 "failed: irq request (IRQ: %d," 1172 "failed: irq request (IRQ: %d, error :%d)\n",
1175 " error :%d)\n",
1176 muic_irq->irq, ret); 1173 muic_irq->irq, ret);
1177 return ret; 1174 return ret;
1178 } 1175 }
diff --git a/drivers/extcon/extcon-max77843.c b/drivers/extcon/extcon-max77843.c
new file mode 100644
index 000000000000..8db6a926ea07
--- /dev/null
+++ b/drivers/extcon/extcon-max77843.c
@@ -0,0 +1,881 @@
1/*
2 * extcon-max77843.c - Maxim MAX77843 extcon driver to support
3 * MUIC(Micro USB Interface Controller)
4 *
5 * Copyright (C) 2015 Samsung Electronics
6 * Author: Jaewon Kim <jaewon02.kim@samsung.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 */
13
14#include <linux/extcon.h>
15#include <linux/i2c.h>
16#include <linux/interrupt.h>
17#include <linux/kernel.h>
18#include <linux/mfd/max77843-private.h>
19#include <linux/module.h>
20#include <linux/platform_device.h>
21#include <linux/workqueue.h>
22
23#define DELAY_MS_DEFAULT 15000 /* unit: millisecond */
24
25enum max77843_muic_status {
26 MAX77843_MUIC_STATUS1 = 0,
27 MAX77843_MUIC_STATUS2,
28 MAX77843_MUIC_STATUS3,
29
30 MAX77843_MUIC_STATUS_NUM,
31};
32
33struct max77843_muic_info {
34 struct device *dev;
35 struct max77843 *max77843;
36 struct extcon_dev *edev;
37
38 struct mutex mutex;
39 struct work_struct irq_work;
40 struct delayed_work wq_detcable;
41
42 u8 status[MAX77843_MUIC_STATUS_NUM];
43 int prev_cable_type;
44 int prev_chg_type;
45 int prev_gnd_type;
46
47 bool irq_adc;
48 bool irq_chg;
49};
50
51enum max77843_muic_cable_group {
52 MAX77843_CABLE_GROUP_ADC = 0,
53 MAX77843_CABLE_GROUP_ADC_GND,
54 MAX77843_CABLE_GROUP_CHG,
55};
56
57enum max77843_muic_adc_debounce_time {
58 MAX77843_DEBOUNCE_TIME_5MS = 0,
59 MAX77843_DEBOUNCE_TIME_10MS,
60 MAX77843_DEBOUNCE_TIME_25MS,
61 MAX77843_DEBOUNCE_TIME_38_62MS,
62};
63
64/* Define accessory cable type */
65enum max77843_muic_accessory_type {
66 MAX77843_MUIC_ADC_GROUND = 0,
67 MAX77843_MUIC_ADC_SEND_END_BUTTON,
68 MAX77843_MUIC_ADC_REMOTE_S1_BUTTON,
69 MAX77843_MUIC_ADC_REMOTE_S2_BUTTON,
70 MAX77843_MUIC_ADC_REMOTE_S3_BUTTON,
71 MAX77843_MUIC_ADC_REMOTE_S4_BUTTON,
72 MAX77843_MUIC_ADC_REMOTE_S5_BUTTON,
73 MAX77843_MUIC_ADC_REMOTE_S6_BUTTON,
74 MAX77843_MUIC_ADC_REMOTE_S7_BUTTON,
75 MAX77843_MUIC_ADC_REMOTE_S8_BUTTON,
76 MAX77843_MUIC_ADC_REMOTE_S9_BUTTON,
77 MAX77843_MUIC_ADC_REMOTE_S10_BUTTON,
78 MAX77843_MUIC_ADC_REMOTE_S11_BUTTON,
79 MAX77843_MUIC_ADC_REMOTE_S12_BUTTON,
80 MAX77843_MUIC_ADC_RESERVED_ACC_1,
81 MAX77843_MUIC_ADC_RESERVED_ACC_2,
82 MAX77843_MUIC_ADC_RESERVED_ACC_3,
83 MAX77843_MUIC_ADC_RESERVED_ACC_4,
84 MAX77843_MUIC_ADC_RESERVED_ACC_5,
85 MAX77843_MUIC_ADC_AUDIO_DEVICE_TYPE2,
86 MAX77843_MUIC_ADC_PHONE_POWERED_DEV,
87 MAX77843_MUIC_ADC_TTY_CONVERTER,
88 MAX77843_MUIC_ADC_UART_CABLE,
89 MAX77843_MUIC_ADC_CEA936A_TYPE1_CHG,
90 MAX77843_MUIC_ADC_FACTORY_MODE_USB_OFF,
91 MAX77843_MUIC_ADC_FACTORY_MODE_USB_ON,
92 MAX77843_MUIC_ADC_AV_CABLE_NOLOAD,
93 MAX77843_MUIC_ADC_CEA936A_TYPE2_CHG,
94 MAX77843_MUIC_ADC_FACTORY_MODE_UART_OFF,
95 MAX77843_MUIC_ADC_FACTORY_MODE_UART_ON,
96 MAX77843_MUIC_ADC_AUDIO_DEVICE_TYPE1,
97 MAX77843_MUIC_ADC_OPEN,
98
99 /* The blow accessories should check
100 not only ADC value but also ADC1K and VBVolt value. */
101 /* Offset|ADC1K|VBVolt| */
102 MAX77843_MUIC_GND_USB_HOST = 0x100, /* 0x1| 0| 0| */
103 MAX77843_MUIC_GND_USB_HOST_VB = 0x101, /* 0x1| 0| 1| */
104 MAX77843_MUIC_GND_MHL = 0x102, /* 0x1| 1| 0| */
105 MAX77843_MUIC_GND_MHL_VB = 0x103, /* 0x1| 1| 1| */
106};
107
108/* Define charger cable type */
109enum max77843_muic_charger_type {
110 MAX77843_MUIC_CHG_NONE = 0,
111 MAX77843_MUIC_CHG_USB,
112 MAX77843_MUIC_CHG_DOWNSTREAM,
113 MAX77843_MUIC_CHG_DEDICATED,
114 MAX77843_MUIC_CHG_SPECIAL_500MA,
115 MAX77843_MUIC_CHG_SPECIAL_1A,
116 MAX77843_MUIC_CHG_SPECIAL_BIAS,
117 MAX77843_MUIC_CHG_RESERVED,
118 MAX77843_MUIC_CHG_GND,
119};
120
121enum {
122 MAX77843_CABLE_USB = 0,
123 MAX77843_CABLE_USB_HOST,
124 MAX77843_CABLE_TA,
125 MAX77843_CABLE_CHARGE_DOWNSTREAM,
126 MAX77843_CABLE_FAST_CHARGER,
127 MAX77843_CABLE_SLOW_CHARGER,
128 MAX77843_CABLE_MHL,
129 MAX77843_CABLE_MHL_TA,
130 MAX77843_CABLE_JIG_USB_ON,
131 MAX77843_CABLE_JIG_USB_OFF,
132 MAX77843_CABLE_JIG_UART_ON,
133 MAX77843_CABLE_JIG_UART_OFF,
134
135 MAX77843_CABLE_NUM,
136};
137
138static const char *max77843_extcon_cable[] = {
139 [MAX77843_CABLE_USB] = "USB",
140 [MAX77843_CABLE_USB_HOST] = "USB-HOST",
141 [MAX77843_CABLE_TA] = "TA",
142 [MAX77843_CABLE_CHARGE_DOWNSTREAM] = "CHARGER-DOWNSTREAM",
143 [MAX77843_CABLE_FAST_CHARGER] = "FAST-CHARGER",
144 [MAX77843_CABLE_SLOW_CHARGER] = "SLOW-CHARGER",
145 [MAX77843_CABLE_MHL] = "MHL",
146 [MAX77843_CABLE_MHL_TA] = "MHL-TA",
147 [MAX77843_CABLE_JIG_USB_ON] = "JIG-USB-ON",
148 [MAX77843_CABLE_JIG_USB_OFF] = "JIG-USB-OFF",
149 [MAX77843_CABLE_JIG_UART_ON] = "JIG-UART-ON",
150 [MAX77843_CABLE_JIG_UART_OFF] = "JIG-UART-OFF",
151};
152
153struct max77843_muic_irq {
154 unsigned int irq;
155 const char *name;
156 unsigned int virq;
157};
158
159static struct max77843_muic_irq max77843_muic_irqs[] = {
160 { MAX77843_MUIC_IRQ_INT1_ADC, "MUIC-ADC" },
161 { MAX77843_MUIC_IRQ_INT1_ADCERROR, "MUIC-ADC_ERROR" },
162 { MAX77843_MUIC_IRQ_INT1_ADC1K, "MUIC-ADC1K" },
163 { MAX77843_MUIC_IRQ_INT2_CHGTYP, "MUIC-CHGTYP" },
164 { MAX77843_MUIC_IRQ_INT2_CHGDETRUN, "MUIC-CHGDETRUN" },
165 { MAX77843_MUIC_IRQ_INT2_DCDTMR, "MUIC-DCDTMR" },
166 { MAX77843_MUIC_IRQ_INT2_DXOVP, "MUIC-DXOVP" },
167 { MAX77843_MUIC_IRQ_INT2_VBVOLT, "MUIC-VBVOLT" },
168 { MAX77843_MUIC_IRQ_INT3_VBADC, "MUIC-VBADC" },
169 { MAX77843_MUIC_IRQ_INT3_VDNMON, "MUIC-VDNMON" },
170 { MAX77843_MUIC_IRQ_INT3_DNRES, "MUIC-DNRES" },
171 { MAX77843_MUIC_IRQ_INT3_MPNACK, "MUIC-MPNACK"},
172 { MAX77843_MUIC_IRQ_INT3_MRXBUFOW, "MUIC-MRXBUFOW"},
173 { MAX77843_MUIC_IRQ_INT3_MRXTRF, "MUIC-MRXTRF"},
174 { MAX77843_MUIC_IRQ_INT3_MRXPERR, "MUIC-MRXPERR"},
175 { MAX77843_MUIC_IRQ_INT3_MRXRDY, "MUIC-MRXRDY"},
176};
177
178static const struct regmap_config max77843_muic_regmap_config = {
179 .reg_bits = 8,
180 .val_bits = 8,
181 .max_register = MAX77843_MUIC_REG_END,
182};
183
184static const struct regmap_irq max77843_muic_irq[] = {
185 /* INT1 interrupt */
186 { .reg_offset = 0, .mask = MAX77843_MUIC_ADC, },
187 { .reg_offset = 0, .mask = MAX77843_MUIC_ADCERROR, },
188 { .reg_offset = 0, .mask = MAX77843_MUIC_ADC1K, },
189
190 /* INT2 interrupt */
191 { .reg_offset = 1, .mask = MAX77843_MUIC_CHGTYP, },
192 { .reg_offset = 1, .mask = MAX77843_MUIC_CHGDETRUN, },
193 { .reg_offset = 1, .mask = MAX77843_MUIC_DCDTMR, },
194 { .reg_offset = 1, .mask = MAX77843_MUIC_DXOVP, },
195 { .reg_offset = 1, .mask = MAX77843_MUIC_VBVOLT, },
196
197 /* INT3 interrupt */
198 { .reg_offset = 2, .mask = MAX77843_MUIC_VBADC, },
199 { .reg_offset = 2, .mask = MAX77843_MUIC_VDNMON, },
200 { .reg_offset = 2, .mask = MAX77843_MUIC_DNRES, },
201 { .reg_offset = 2, .mask = MAX77843_MUIC_MPNACK, },
202 { .reg_offset = 2, .mask = MAX77843_MUIC_MRXBUFOW, },
203 { .reg_offset = 2, .mask = MAX77843_MUIC_MRXTRF, },
204 { .reg_offset = 2, .mask = MAX77843_MUIC_MRXPERR, },
205 { .reg_offset = 2, .mask = MAX77843_MUIC_MRXRDY, },
206};
207
208static const struct regmap_irq_chip max77843_muic_irq_chip = {
209 .name = "max77843-muic",
210 .status_base = MAX77843_MUIC_REG_INT1,
211 .mask_base = MAX77843_MUIC_REG_INTMASK1,
212 .mask_invert = true,
213 .num_regs = 3,
214 .irqs = max77843_muic_irq,
215 .num_irqs = ARRAY_SIZE(max77843_muic_irq),
216};
217
218static int max77843_muic_set_path(struct max77843_muic_info *info,
219 u8 val, bool attached)
220{
221 struct max77843 *max77843 = info->max77843;
222 int ret = 0;
223 unsigned int ctrl1, ctrl2;
224
225 if (attached)
226 ctrl1 = val;
227 else
228 ctrl1 = CONTROL1_SW_OPEN;
229
230 ret = regmap_update_bits(max77843->regmap_muic,
231 MAX77843_MUIC_REG_CONTROL1,
232 CONTROL1_COM_SW, ctrl1);
233 if (ret < 0) {
234 dev_err(info->dev, "Cannot switch MUIC port\n");
235 return ret;
236 }
237
238 if (attached)
239 ctrl2 = MAX77843_MUIC_CONTROL2_CPEN_MASK;
240 else
241 ctrl2 = MAX77843_MUIC_CONTROL2_LOWPWR_MASK;
242
243 ret = regmap_update_bits(max77843->regmap_muic,
244 MAX77843_MUIC_REG_CONTROL2,
245 MAX77843_MUIC_CONTROL2_LOWPWR_MASK |
246 MAX77843_MUIC_CONTROL2_CPEN_MASK, ctrl2);
247 if (ret < 0) {
248 dev_err(info->dev, "Cannot update lowpower mode\n");
249 return ret;
250 }
251
252 dev_dbg(info->dev,
253 "CONTROL1 : 0x%02x, CONTROL2 : 0x%02x, state : %s\n",
254 ctrl1, ctrl2, attached ? "attached" : "detached");
255
256 return 0;
257}
258
259static int max77843_muic_get_cable_type(struct max77843_muic_info *info,
260 enum max77843_muic_cable_group group, bool *attached)
261{
262 int adc, chg_type, cable_type, gnd_type;
263
264 adc = info->status[MAX77843_MUIC_STATUS1] &
265 MAX77843_MUIC_STATUS1_ADC_MASK;
266 adc >>= STATUS1_ADC_SHIFT;
267
268 switch (group) {
269 case MAX77843_CABLE_GROUP_ADC:
270 if (adc == MAX77843_MUIC_ADC_OPEN) {
271 *attached = false;
272 cable_type = info->prev_cable_type;
273 info->prev_cable_type = MAX77843_MUIC_ADC_OPEN;
274 } else {
275 *attached = true;
276 cable_type = info->prev_cable_type = adc;
277 }
278 break;
279 case MAX77843_CABLE_GROUP_CHG:
280 chg_type = info->status[MAX77843_MUIC_STATUS2] &
281 MAX77843_MUIC_STATUS2_CHGTYP_MASK;
282
283 /* Check GROUND accessory with charger cable */
284 if (adc == MAX77843_MUIC_ADC_GROUND) {
285 if (chg_type == MAX77843_MUIC_CHG_NONE) {
286 /* The following state when charger cable is
287 * disconnected but the GROUND accessory still
288 * connected */
289 *attached = false;
290 cable_type = info->prev_chg_type;
291 info->prev_chg_type = MAX77843_MUIC_CHG_NONE;
292 } else {
293
294 /* The following state when charger cable is
295 * connected on the GROUND accessory */
296 *attached = true;
297 cable_type = MAX77843_MUIC_CHG_GND;
298 info->prev_chg_type = MAX77843_MUIC_CHG_GND;
299 }
300 break;
301 }
302
303 if (chg_type == MAX77843_MUIC_CHG_NONE) {
304 *attached = false;
305 cable_type = info->prev_chg_type;
306 info->prev_chg_type = MAX77843_MUIC_CHG_NONE;
307 } else {
308 *attached = true;
309 cable_type = info->prev_chg_type = chg_type;
310 }
311 break;
312 case MAX77843_CABLE_GROUP_ADC_GND:
313 if (adc == MAX77843_MUIC_ADC_OPEN) {
314 *attached = false;
315 cable_type = info->prev_gnd_type;
316 info->prev_gnd_type = MAX77843_MUIC_ADC_OPEN;
317 } else {
318 *attached = true;
319
320 /* Offset|ADC1K|VBVolt|
321 * 0x1| 0| 0| USB-HOST
322 * 0x1| 0| 1| USB-HOST with VB
323 * 0x1| 1| 0| MHL
324 * 0x1| 1| 1| MHL with VB */
325 /* Get ADC1K register bit */
326 gnd_type = (info->status[MAX77843_MUIC_STATUS1] &
327 MAX77843_MUIC_STATUS1_ADC1K_MASK);
328
329 /* Get VBVolt register bit */
330 gnd_type |= (info->status[MAX77843_MUIC_STATUS2] &
331 MAX77843_MUIC_STATUS2_VBVOLT_MASK);
332 gnd_type >>= STATUS2_VBVOLT_SHIFT;
333
334 /* Offset of GND cable */
335 gnd_type |= MAX77843_MUIC_GND_USB_HOST;
336 cable_type = info->prev_gnd_type = gnd_type;
337 }
338 break;
339 default:
340 dev_err(info->dev, "Unknown cable group (%d)\n", group);
341 cable_type = -EINVAL;
342 break;
343 }
344
345 return cable_type;
346}
347
348static int max77843_muic_adc_gnd_handler(struct max77843_muic_info *info)
349{
350 int ret, gnd_cable_type;
351 bool attached;
352
353 gnd_cable_type = max77843_muic_get_cable_type(info,
354 MAX77843_CABLE_GROUP_ADC_GND, &attached);
355 dev_dbg(info->dev, "external connector is %s (gnd:0x%02x)\n",
356 attached ? "attached" : "detached", gnd_cable_type);
357
358 switch (gnd_cable_type) {
359 case MAX77843_MUIC_GND_USB_HOST:
360 case MAX77843_MUIC_GND_USB_HOST_VB:
361 ret = max77843_muic_set_path(info, CONTROL1_SW_USB, attached);
362 if (ret < 0)
363 return ret;
364
365 extcon_set_cable_state(info->edev, "USB-HOST", attached);
366 break;
367 case MAX77843_MUIC_GND_MHL_VB:
368 case MAX77843_MUIC_GND_MHL:
369 ret = max77843_muic_set_path(info, CONTROL1_SW_OPEN, attached);
370 if (ret < 0)
371 return ret;
372
373 extcon_set_cable_state(info->edev, "MHL", attached);
374 break;
375 default:
376 dev_err(info->dev, "failed to detect %s accessory(gnd:0x%x)\n",
377 attached ? "attached" : "detached", gnd_cable_type);
378 return -EINVAL;
379 }
380
381 return 0;
382}
383
384static int max77843_muic_jig_handler(struct max77843_muic_info *info,
385 int cable_type, bool attached)
386{
387 int ret;
388
389 dev_dbg(info->dev, "external connector is %s (adc:0x%02x)\n",
390 attached ? "attached" : "detached", cable_type);
391
392 switch (cable_type) {
393 case MAX77843_MUIC_ADC_FACTORY_MODE_USB_OFF:
394 ret = max77843_muic_set_path(info, CONTROL1_SW_USB, attached);
395 if (ret < 0)
396 return ret;
397 extcon_set_cable_state(info->edev, "JIG-USB-OFF", attached);
398 break;
399 case MAX77843_MUIC_ADC_FACTORY_MODE_USB_ON:
400 ret = max77843_muic_set_path(info, CONTROL1_SW_USB, attached);
401 if (ret < 0)
402 return ret;
403 extcon_set_cable_state(info->edev, "JIG-USB-ON", attached);
404 break;
405 case MAX77843_MUIC_ADC_FACTORY_MODE_UART_OFF:
406 ret = max77843_muic_set_path(info, CONTROL1_SW_UART, attached);
407 if (ret < 0)
408 return ret;
409 extcon_set_cable_state(info->edev, "JIG-UART-OFF", attached);
410 break;
411 default:
412 ret = max77843_muic_set_path(info, CONTROL1_SW_OPEN, attached);
413 if (ret < 0)
414 return ret;
415 break;
416 }
417
418 return 0;
419}
420
421static int max77843_muic_adc_handler(struct max77843_muic_info *info)
422{
423 int ret, cable_type;
424 bool attached;
425
426 cable_type = max77843_muic_get_cable_type(info,
427 MAX77843_CABLE_GROUP_ADC, &attached);
428
429 dev_dbg(info->dev,
430 "external connector is %s (adc:0x%02x, prev_adc:0x%x)\n",
431 attached ? "attached" : "detached", cable_type,
432 info->prev_cable_type);
433
434 switch (cable_type) {
435 case MAX77843_MUIC_ADC_GROUND:
436 ret = max77843_muic_adc_gnd_handler(info);
437 if (ret < 0)
438 return ret;
439 break;
440 case MAX77843_MUIC_ADC_FACTORY_MODE_USB_OFF:
441 case MAX77843_MUIC_ADC_FACTORY_MODE_USB_ON:
442 case MAX77843_MUIC_ADC_FACTORY_MODE_UART_OFF:
443 ret = max77843_muic_jig_handler(info, cable_type, attached);
444 if (ret < 0)
445 return ret;
446 break;
447 case MAX77843_MUIC_ADC_SEND_END_BUTTON:
448 case MAX77843_MUIC_ADC_REMOTE_S1_BUTTON:
449 case MAX77843_MUIC_ADC_REMOTE_S2_BUTTON:
450 case MAX77843_MUIC_ADC_REMOTE_S3_BUTTON:
451 case MAX77843_MUIC_ADC_REMOTE_S4_BUTTON:
452 case MAX77843_MUIC_ADC_REMOTE_S5_BUTTON:
453 case MAX77843_MUIC_ADC_REMOTE_S6_BUTTON:
454 case MAX77843_MUIC_ADC_REMOTE_S7_BUTTON:
455 case MAX77843_MUIC_ADC_REMOTE_S8_BUTTON:
456 case MAX77843_MUIC_ADC_REMOTE_S9_BUTTON:
457 case MAX77843_MUIC_ADC_REMOTE_S10_BUTTON:
458 case MAX77843_MUIC_ADC_REMOTE_S11_BUTTON:
459 case MAX77843_MUIC_ADC_REMOTE_S12_BUTTON:
460 case MAX77843_MUIC_ADC_RESERVED_ACC_1:
461 case MAX77843_MUIC_ADC_RESERVED_ACC_2:
462 case MAX77843_MUIC_ADC_RESERVED_ACC_3:
463 case MAX77843_MUIC_ADC_RESERVED_ACC_4:
464 case MAX77843_MUIC_ADC_RESERVED_ACC_5:
465 case MAX77843_MUIC_ADC_AUDIO_DEVICE_TYPE2:
466 case MAX77843_MUIC_ADC_PHONE_POWERED_DEV:
467 case MAX77843_MUIC_ADC_TTY_CONVERTER:
468 case MAX77843_MUIC_ADC_UART_CABLE:
469 case MAX77843_MUIC_ADC_CEA936A_TYPE1_CHG:
470 case MAX77843_MUIC_ADC_AV_CABLE_NOLOAD:
471 case MAX77843_MUIC_ADC_CEA936A_TYPE2_CHG:
472 case MAX77843_MUIC_ADC_FACTORY_MODE_UART_ON:
473 case MAX77843_MUIC_ADC_AUDIO_DEVICE_TYPE1:
474 case MAX77843_MUIC_ADC_OPEN:
475 dev_err(info->dev,
476 "accessory is %s but it isn't used (adc:0x%x)\n",
477 attached ? "attached" : "detached", cable_type);
478 return -EAGAIN;
479 default:
480 dev_err(info->dev,
481 "failed to detect %s accessory (adc:0x%x)\n",
482 attached ? "attached" : "detached", cable_type);
483 return -EINVAL;
484 }
485
486 return 0;
487}
488
489static int max77843_muic_chg_handler(struct max77843_muic_info *info)
490{
491 int ret, chg_type, gnd_type;
492 bool attached;
493
494 chg_type = max77843_muic_get_cable_type(info,
495 MAX77843_CABLE_GROUP_CHG, &attached);
496
497 dev_dbg(info->dev,
498 "external connector is %s(chg_type:0x%x, prev_chg_type:0x%x)\n",
499 attached ? "attached" : "detached",
500 chg_type, info->prev_chg_type);
501
502 switch (chg_type) {
503 case MAX77843_MUIC_CHG_USB:
504 ret = max77843_muic_set_path(info, CONTROL1_SW_USB, attached);
505 if (ret < 0)
506 return ret;
507
508 extcon_set_cable_state(info->edev, "USB", attached);
509 break;
510 case MAX77843_MUIC_CHG_DOWNSTREAM:
511 ret = max77843_muic_set_path(info, CONTROL1_SW_OPEN, attached);
512 if (ret < 0)
513 return ret;
514
515 extcon_set_cable_state(info->edev,
516 "CHARGER-DOWNSTREAM", attached);
517 break;
518 case MAX77843_MUIC_CHG_DEDICATED:
519 ret = max77843_muic_set_path(info, CONTROL1_SW_OPEN, attached);
520 if (ret < 0)
521 return ret;
522
523 extcon_set_cable_state(info->edev, "TA", attached);
524 break;
525 case MAX77843_MUIC_CHG_SPECIAL_500MA:
526 ret = max77843_muic_set_path(info, CONTROL1_SW_OPEN, attached);
527 if (ret < 0)
528 return ret;
529
530 extcon_set_cable_state(info->edev, "SLOW-CHAREGER", attached);
531 break;
532 case MAX77843_MUIC_CHG_SPECIAL_1A:
533 ret = max77843_muic_set_path(info, CONTROL1_SW_OPEN, attached);
534 if (ret < 0)
535 return ret;
536
537 extcon_set_cable_state(info->edev, "FAST-CHARGER", attached);
538 break;
539 case MAX77843_MUIC_CHG_GND:
540 gnd_type = max77843_muic_get_cable_type(info,
541 MAX77843_CABLE_GROUP_ADC_GND, &attached);
542
543 /* Charger cable on MHL accessory is attach or detach */
544 if (gnd_type == MAX77843_MUIC_GND_MHL_VB)
545 extcon_set_cable_state(info->edev, "MHL-TA", true);
546 else if (gnd_type == MAX77843_MUIC_GND_MHL)
547 extcon_set_cable_state(info->edev, "MHL-TA", false);
548 break;
549 case MAX77843_MUIC_CHG_NONE:
550 break;
551 default:
552 dev_err(info->dev,
553 "failed to detect %s accessory (chg_type:0x%x)\n",
554 attached ? "attached" : "detached", chg_type);
555
556 max77843_muic_set_path(info, CONTROL1_SW_OPEN, attached);
557 return -EINVAL;
558 }
559
560 return 0;
561}
562
563static void max77843_muic_irq_work(struct work_struct *work)
564{
565 struct max77843_muic_info *info = container_of(work,
566 struct max77843_muic_info, irq_work);
567 struct max77843 *max77843 = info->max77843;
568 int ret = 0;
569
570 mutex_lock(&info->mutex);
571
572 ret = regmap_bulk_read(max77843->regmap_muic,
573 MAX77843_MUIC_REG_STATUS1, info->status,
574 MAX77843_MUIC_STATUS_NUM);
575 if (ret) {
576 dev_err(info->dev, "Cannot read STATUS registers\n");
577 mutex_unlock(&info->mutex);
578 return;
579 }
580
581 if (info->irq_adc) {
582 ret = max77843_muic_adc_handler(info);
583 if (ret)
584 dev_err(info->dev, "Unknown cable type\n");
585 info->irq_adc = false;
586 }
587
588 if (info->irq_chg) {
589 ret = max77843_muic_chg_handler(info);
590 if (ret)
591 dev_err(info->dev, "Unknown charger type\n");
592 info->irq_chg = false;
593 }
594
595 mutex_unlock(&info->mutex);
596}
597
598static irqreturn_t max77843_muic_irq_handler(int irq, void *data)
599{
600 struct max77843_muic_info *info = data;
601 int i, irq_type = -1;
602
603 for (i = 0; i < ARRAY_SIZE(max77843_muic_irqs); i++)
604 if (irq == max77843_muic_irqs[i].virq)
605 irq_type = max77843_muic_irqs[i].irq;
606
607 switch (irq_type) {
608 case MAX77843_MUIC_IRQ_INT1_ADC:
609 case MAX77843_MUIC_IRQ_INT1_ADCERROR:
610 case MAX77843_MUIC_IRQ_INT1_ADC1K:
611 info->irq_adc = true;
612 break;
613 case MAX77843_MUIC_IRQ_INT2_CHGTYP:
614 case MAX77843_MUIC_IRQ_INT2_CHGDETRUN:
615 case MAX77843_MUIC_IRQ_INT2_DCDTMR:
616 case MAX77843_MUIC_IRQ_INT2_DXOVP:
617 case MAX77843_MUIC_IRQ_INT2_VBVOLT:
618 info->irq_chg = true;
619 break;
620 case MAX77843_MUIC_IRQ_INT3_VBADC:
621 case MAX77843_MUIC_IRQ_INT3_VDNMON:
622 case MAX77843_MUIC_IRQ_INT3_DNRES:
623 case MAX77843_MUIC_IRQ_INT3_MPNACK:
624 case MAX77843_MUIC_IRQ_INT3_MRXBUFOW:
625 case MAX77843_MUIC_IRQ_INT3_MRXTRF:
626 case MAX77843_MUIC_IRQ_INT3_MRXPERR:
627 case MAX77843_MUIC_IRQ_INT3_MRXRDY:
628 break;
629 default:
630 dev_err(info->dev, "Cannot recognize IRQ(%d)\n", irq_type);
631 break;
632 }
633
634 schedule_work(&info->irq_work);
635
636 return IRQ_HANDLED;
637}
638
639static void max77843_muic_detect_cable_wq(struct work_struct *work)
640{
641 struct max77843_muic_info *info = container_of(to_delayed_work(work),
642 struct max77843_muic_info, wq_detcable);
643 struct max77843 *max77843 = info->max77843;
644 int chg_type, adc, ret;
645 bool attached;
646
647 mutex_lock(&info->mutex);
648
649 ret = regmap_bulk_read(max77843->regmap_muic,
650 MAX77843_MUIC_REG_STATUS1, info->status,
651 MAX77843_MUIC_STATUS_NUM);
652 if (ret) {
653 dev_err(info->dev, "Cannot read STATUS registers\n");
654 goto err_cable_wq;
655 }
656
657 adc = max77843_muic_get_cable_type(info,
658 MAX77843_CABLE_GROUP_ADC, &attached);
659 if (attached && adc != MAX77843_MUIC_ADC_OPEN) {
660 ret = max77843_muic_adc_handler(info);
661 if (ret < 0) {
662 dev_err(info->dev, "Cannot detect accessory\n");
663 goto err_cable_wq;
664 }
665 }
666
667 chg_type = max77843_muic_get_cable_type(info,
668 MAX77843_CABLE_GROUP_CHG, &attached);
669 if (attached && chg_type != MAX77843_MUIC_CHG_NONE) {
670 ret = max77843_muic_chg_handler(info);
671 if (ret < 0) {
672 dev_err(info->dev, "Cannot detect charger accessory\n");
673 goto err_cable_wq;
674 }
675 }
676
677err_cable_wq:
678 mutex_unlock(&info->mutex);
679}
680
681static int max77843_muic_set_debounce_time(struct max77843_muic_info *info,
682 enum max77843_muic_adc_debounce_time time)
683{
684 struct max77843 *max77843 = info->max77843;
685 int ret;
686
687 switch (time) {
688 case MAX77843_DEBOUNCE_TIME_5MS:
689 case MAX77843_DEBOUNCE_TIME_10MS:
690 case MAX77843_DEBOUNCE_TIME_25MS:
691 case MAX77843_DEBOUNCE_TIME_38_62MS:
692 ret = regmap_update_bits(max77843->regmap_muic,
693 MAX77843_MUIC_REG_CONTROL4,
694 MAX77843_MUIC_CONTROL4_ADCDBSET_MASK,
695 time << CONTROL4_ADCDBSET_SHIFT);
696 if (ret < 0) {
697 dev_err(info->dev, "Cannot write MUIC regmap\n");
698 return ret;
699 }
700 break;
701 default:
702 dev_err(info->dev, "Invalid ADC debounce time\n");
703 return -EINVAL;
704 }
705
706 return 0;
707}
708
709static int max77843_init_muic_regmap(struct max77843 *max77843)
710{
711 int ret;
712
713 max77843->i2c_muic = i2c_new_dummy(max77843->i2c->adapter,
714 I2C_ADDR_MUIC);
715 if (!max77843->i2c_muic) {
716 dev_err(&max77843->i2c->dev,
717 "Cannot allocate I2C device for MUIC\n");
718 return -ENOMEM;
719 }
720
721 i2c_set_clientdata(max77843->i2c_muic, max77843);
722
723 max77843->regmap_muic = devm_regmap_init_i2c(max77843->i2c_muic,
724 &max77843_muic_regmap_config);
725 if (IS_ERR(max77843->regmap_muic)) {
726 ret = PTR_ERR(max77843->regmap_muic);
727 goto err_muic_i2c;
728 }
729
730 ret = regmap_add_irq_chip(max77843->regmap_muic, max77843->irq,
731 IRQF_TRIGGER_LOW | IRQF_ONESHOT | IRQF_SHARED,
732 0, &max77843_muic_irq_chip, &max77843->irq_data_muic);
733 if (ret < 0) {
734 dev_err(&max77843->i2c->dev, "Cannot add MUIC IRQ chip\n");
735 goto err_muic_i2c;
736 }
737
738 return 0;
739
740err_muic_i2c:
741 i2c_unregister_device(max77843->i2c_muic);
742
743 return ret;
744}
745
746static int max77843_muic_probe(struct platform_device *pdev)
747{
748 struct max77843 *max77843 = dev_get_drvdata(pdev->dev.parent);
749 struct max77843_muic_info *info;
750 unsigned int id;
751 int i, ret;
752
753 info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
754 if (!info)
755 return -ENOMEM;
756
757 info->dev = &pdev->dev;
758 info->max77843 = max77843;
759
760 platform_set_drvdata(pdev, info);
761 mutex_init(&info->mutex);
762
763 /* Initialize i2c and regmap */
764 ret = max77843_init_muic_regmap(max77843);
765 if (ret) {
766 dev_err(&pdev->dev, "Failed to init MUIC regmap\n");
767 return ret;
768 }
769
770 /* Turn off auto detection configuration */
771 ret = regmap_update_bits(max77843->regmap_muic,
772 MAX77843_MUIC_REG_CONTROL4,
773 MAX77843_MUIC_CONTROL4_USBAUTO_MASK |
774 MAX77843_MUIC_CONTROL4_FCTAUTO_MASK,
775 CONTROL4_AUTO_DISABLE);
776
777 /* Initialize extcon device */
778 info->edev = devm_extcon_dev_allocate(&pdev->dev,
779 max77843_extcon_cable);
780 if (IS_ERR(info->edev)) {
781 dev_err(&pdev->dev, "Failed to allocate memory for extcon\n");
782 ret = -ENODEV;
783 goto err_muic_irq;
784 }
785
786 ret = devm_extcon_dev_register(&pdev->dev, info->edev);
787 if (ret) {
788 dev_err(&pdev->dev, "Failed to register extcon device\n");
789 goto err_muic_irq;
790 }
791
792 /* Set ADC debounce time */
793 max77843_muic_set_debounce_time(info, MAX77843_DEBOUNCE_TIME_25MS);
794
795 /* Set initial path for UART */
796 max77843_muic_set_path(info, CONTROL1_SW_UART, true);
797
798 /* Check revision number of MUIC device */
799 ret = regmap_read(max77843->regmap_muic, MAX77843_MUIC_REG_ID, &id);
800 if (ret < 0) {
801 dev_err(&pdev->dev, "Failed to read revision number\n");
802 goto err_muic_irq;
803 }
804 dev_info(info->dev, "MUIC device ID : 0x%x\n", id);
805
806 /* Support virtual irq domain for max77843 MUIC device */
807 INIT_WORK(&info->irq_work, max77843_muic_irq_work);
808
809 for (i = 0; i < ARRAY_SIZE(max77843_muic_irqs); i++) {
810 struct max77843_muic_irq *muic_irq = &max77843_muic_irqs[i];
811 unsigned int virq = 0;
812
813 virq = regmap_irq_get_virq(max77843->irq_data_muic,
814 muic_irq->irq);
815 if (virq <= 0) {
816 ret = -EINVAL;
817 goto err_muic_irq;
818 }
819 muic_irq->virq = virq;
820
821 ret = devm_request_threaded_irq(&pdev->dev, virq, NULL,
822 max77843_muic_irq_handler, IRQF_NO_SUSPEND,
823 muic_irq->name, info);
824 if (ret) {
825 dev_err(&pdev->dev,
826 "Failed to request irq (IRQ: %d, error: %d)\n",
827 muic_irq->irq, ret);
828 goto err_muic_irq;
829 }
830 }
831
832 /* Detect accessory after completing the initialization of platform */
833 INIT_DELAYED_WORK(&info->wq_detcable, max77843_muic_detect_cable_wq);
834 queue_delayed_work(system_power_efficient_wq,
835 &info->wq_detcable, msecs_to_jiffies(DELAY_MS_DEFAULT));
836
837 return 0;
838
839err_muic_irq:
840 regmap_del_irq_chip(max77843->irq, max77843->irq_data_muic);
841 i2c_unregister_device(max77843->i2c_muic);
842
843 return ret;
844}
845
846static int max77843_muic_remove(struct platform_device *pdev)
847{
848 struct max77843_muic_info *info = platform_get_drvdata(pdev);
849 struct max77843 *max77843 = info->max77843;
850
851 cancel_work_sync(&info->irq_work);
852 regmap_del_irq_chip(max77843->irq, max77843->irq_data_muic);
853 i2c_unregister_device(max77843->i2c_muic);
854
855 return 0;
856}
857
858static const struct platform_device_id max77843_muic_id[] = {
859 { "max77843-muic", },
860 { /* sentinel */ },
861};
862MODULE_DEVICE_TABLE(platform, max77843_muic_id);
863
864static struct platform_driver max77843_muic_driver = {
865 .driver = {
866 .name = "max77843-muic",
867 },
868 .probe = max77843_muic_probe,
869 .remove = max77843_muic_remove,
870 .id_table = max77843_muic_id,
871};
872
873static int __init max77843_muic_init(void)
874{
875 return platform_driver_register(&max77843_muic_driver);
876}
877subsys_initcall(max77843_muic_init);
878
879MODULE_DESCRIPTION("Maxim MAX77843 Extcon driver");
880MODULE_AUTHOR("Jaewon Kim <jaewon02.kim@samsung.com>");
881MODULE_LICENSE("GPL");
diff --git a/drivers/extcon/extcon-max8997.c b/drivers/extcon/extcon-max8997.c
index fc1678fa95c4..5774e56c6422 100644
--- a/drivers/extcon/extcon-max8997.c
+++ b/drivers/extcon/extcon-max8997.c
@@ -579,8 +579,6 @@ static void max8997_muic_irq_work(struct work_struct *work)
579 dev_err(info->dev, "failed to handle MUIC interrupt\n"); 579 dev_err(info->dev, "failed to handle MUIC interrupt\n");
580 580
581 mutex_unlock(&info->mutex); 581 mutex_unlock(&info->mutex);
582
583 return;
584} 582}
585 583
586static irqreturn_t max8997_muic_irq_handler(int irq, void *data) 584static irqreturn_t max8997_muic_irq_handler(int irq, void *data)
@@ -689,8 +687,7 @@ static int max8997_muic_probe(struct platform_device *pdev)
689 muic_irq->name, info); 687 muic_irq->name, info);
690 if (ret) { 688 if (ret) {
691 dev_err(&pdev->dev, 689 dev_err(&pdev->dev,
692 "failed: irq request (IRQ: %d," 690 "failed: irq request (IRQ: %d, error :%d)\n",
693 " error :%d)\n",
694 muic_irq->irq, ret); 691 muic_irq->irq, ret);
695 goto err_irq; 692 goto err_irq;
696 } 693 }
diff --git a/drivers/extcon/extcon-rt8973a.c b/drivers/extcon/extcon-rt8973a.c
index a784b2d5ee72..9ccd5af89d1c 100644
--- a/drivers/extcon/extcon-rt8973a.c
+++ b/drivers/extcon/extcon-rt8973a.c
@@ -582,10 +582,8 @@ static int rt8973a_muic_i2c_probe(struct i2c_client *i2c,
582 return -EINVAL; 582 return -EINVAL;
583 583
584 info = devm_kzalloc(&i2c->dev, sizeof(*info), GFP_KERNEL); 584 info = devm_kzalloc(&i2c->dev, sizeof(*info), GFP_KERNEL);
585 if (!info) { 585 if (!info)
586 dev_err(&i2c->dev, "failed to allocate memory\n");
587 return -ENOMEM; 586 return -ENOMEM;
588 }
589 i2c_set_clientdata(i2c, info); 587 i2c_set_clientdata(i2c, info);
590 588
591 info->dev = &i2c->dev; 589 info->dev = &i2c->dev;
@@ -681,7 +679,7 @@ static int rt8973a_muic_i2c_remove(struct i2c_client *i2c)
681 return 0; 679 return 0;
682} 680}
683 681
684static struct of_device_id rt8973a_dt_match[] = { 682static const struct of_device_id rt8973a_dt_match[] = {
685 { .compatible = "richtek,rt8973a-muic" }, 683 { .compatible = "richtek,rt8973a-muic" },
686 { }, 684 { },
687}; 685};
diff --git a/drivers/extcon/extcon-sm5502.c b/drivers/extcon/extcon-sm5502.c
index b0f7bd82af90..2f93cf307852 100644
--- a/drivers/extcon/extcon-sm5502.c
+++ b/drivers/extcon/extcon-sm5502.c
@@ -359,8 +359,8 @@ static unsigned int sm5502_muic_get_cable_type(struct sm5502_muic_info *info)
359 break; 359 break;
360 default: 360 default:
361 dev_dbg(info->dev, 361 dev_dbg(info->dev,
362 "cannot identify the cable type: adc(0x%x) " 362 "cannot identify the cable type: adc(0x%x)\n",
363 "dev_type1(0x%x)\n", adc, dev_type1); 363 adc);
364 return -EINVAL; 364 return -EINVAL;
365 }; 365 };
366 break; 366 break;
@@ -659,7 +659,7 @@ static int sm5502_muic_i2c_remove(struct i2c_client *i2c)
659 return 0; 659 return 0;
660} 660}
661 661
662static struct of_device_id sm5502_dt_match[] = { 662static const struct of_device_id sm5502_dt_match[] = {
663 { .compatible = "siliconmitus,sm5502-muic" }, 663 { .compatible = "siliconmitus,sm5502-muic" },
664 { }, 664 { },
665}; 665};
diff --git a/drivers/extcon/extcon-usb-gpio.c b/drivers/extcon/extcon-usb-gpio.c
new file mode 100644
index 000000000000..de67fce18984
--- /dev/null
+++ b/drivers/extcon/extcon-usb-gpio.c
@@ -0,0 +1,237 @@
1/**
2 * drivers/extcon/extcon-usb-gpio.c - USB GPIO extcon driver
3 *
4 * Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com
5 * Author: Roger Quadros <rogerq@ti.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 */
16
17#include <linux/extcon.h>
18#include <linux/init.h>
19#include <linux/interrupt.h>
20#include <linux/irq.h>
21#include <linux/kernel.h>
22#include <linux/module.h>
23#include <linux/of_gpio.h>
24#include <linux/platform_device.h>
25#include <linux/slab.h>
26#include <linux/workqueue.h>
27
28#define USB_GPIO_DEBOUNCE_MS 20 /* ms */
29
30struct usb_extcon_info {
31 struct device *dev;
32 struct extcon_dev *edev;
33
34 struct gpio_desc *id_gpiod;
35 int id_irq;
36
37 unsigned long debounce_jiffies;
38 struct delayed_work wq_detcable;
39};
40
41/* List of detectable cables */
42enum {
43 EXTCON_CABLE_USB = 0,
44 EXTCON_CABLE_USB_HOST,
45
46 EXTCON_CABLE_END,
47};
48
49static const char *usb_extcon_cable[] = {
50 [EXTCON_CABLE_USB] = "USB",
51 [EXTCON_CABLE_USB_HOST] = "USB-HOST",
52 NULL,
53};
54
55static void usb_extcon_detect_cable(struct work_struct *work)
56{
57 int id;
58 struct usb_extcon_info *info = container_of(to_delayed_work(work),
59 struct usb_extcon_info,
60 wq_detcable);
61
62 /* check ID and update cable state */
63 id = gpiod_get_value_cansleep(info->id_gpiod);
64 if (id) {
65 /*
66 * ID = 1 means USB HOST cable detached.
67 * As we don't have event for USB peripheral cable attached,
68 * we simulate USB peripheral attach here.
69 */
70 extcon_set_cable_state(info->edev,
71 usb_extcon_cable[EXTCON_CABLE_USB_HOST],
72 false);
73 extcon_set_cable_state(info->edev,
74 usb_extcon_cable[EXTCON_CABLE_USB],
75 true);
76 } else {
77 /*
78 * ID = 0 means USB HOST cable attached.
79 * As we don't have event for USB peripheral cable detached,
80 * we simulate USB peripheral detach here.
81 */
82 extcon_set_cable_state(info->edev,
83 usb_extcon_cable[EXTCON_CABLE_USB],
84 false);
85 extcon_set_cable_state(info->edev,
86 usb_extcon_cable[EXTCON_CABLE_USB_HOST],
87 true);
88 }
89}
90
91static irqreturn_t usb_irq_handler(int irq, void *dev_id)
92{
93 struct usb_extcon_info *info = dev_id;
94
95 queue_delayed_work(system_power_efficient_wq, &info->wq_detcable,
96 info->debounce_jiffies);
97
98 return IRQ_HANDLED;
99}
100
101static int usb_extcon_probe(struct platform_device *pdev)
102{
103 struct device *dev = &pdev->dev;
104 struct device_node *np = dev->of_node;
105 struct usb_extcon_info *info;
106 int ret;
107
108 if (!np)
109 return -EINVAL;
110
111 info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
112 if (!info)
113 return -ENOMEM;
114
115 info->dev = dev;
116 info->id_gpiod = devm_gpiod_get(&pdev->dev, "id");
117 if (IS_ERR(info->id_gpiod)) {
118 dev_err(dev, "failed to get ID GPIO\n");
119 return PTR_ERR(info->id_gpiod);
120 }
121
122 ret = gpiod_set_debounce(info->id_gpiod,
123 USB_GPIO_DEBOUNCE_MS * 1000);
124 if (ret < 0)
125 info->debounce_jiffies = msecs_to_jiffies(USB_GPIO_DEBOUNCE_MS);
126
127 INIT_DELAYED_WORK(&info->wq_detcable, usb_extcon_detect_cable);
128
129 info->id_irq = gpiod_to_irq(info->id_gpiod);
130 if (info->id_irq < 0) {
131 dev_err(dev, "failed to get ID IRQ\n");
132 return info->id_irq;
133 }
134
135 ret = devm_request_threaded_irq(dev, info->id_irq, NULL,
136 usb_irq_handler,
137 IRQF_TRIGGER_RISING |
138 IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
139 pdev->name, info);
140 if (ret < 0) {
141 dev_err(dev, "failed to request handler for ID IRQ\n");
142 return ret;
143 }
144
145 info->edev = devm_extcon_dev_allocate(dev, usb_extcon_cable);
146 if (IS_ERR(info->edev)) {
147 dev_err(dev, "failed to allocate extcon device\n");
148 return -ENOMEM;
149 }
150
151 ret = devm_extcon_dev_register(dev, info->edev);
152 if (ret < 0) {
153 dev_err(dev, "failed to register extcon device\n");
154 return ret;
155 }
156
157 platform_set_drvdata(pdev, info);
158 device_init_wakeup(dev, 1);
159
160 /* Perform initial detection */
161 usb_extcon_detect_cable(&info->wq_detcable.work);
162
163 return 0;
164}
165
166static int usb_extcon_remove(struct platform_device *pdev)
167{
168 struct usb_extcon_info *info = platform_get_drvdata(pdev);
169
170 cancel_delayed_work_sync(&info->wq_detcable);
171
172 return 0;
173}
174
175#ifdef CONFIG_PM_SLEEP
176static int usb_extcon_suspend(struct device *dev)
177{
178 struct usb_extcon_info *info = dev_get_drvdata(dev);
179 int ret = 0;
180
181 if (device_may_wakeup(dev)) {
182 ret = enable_irq_wake(info->id_irq);
183 if (ret)
184 return ret;
185 }
186
187 /*
188 * We don't want to process any IRQs after this point
189 * as GPIOs used behind I2C subsystem might not be
190 * accessible until resume completes. So disable IRQ.
191 */
192 disable_irq(info->id_irq);
193
194 return ret;
195}
196
197static int usb_extcon_resume(struct device *dev)
198{
199 struct usb_extcon_info *info = dev_get_drvdata(dev);
200 int ret = 0;
201
202 if (device_may_wakeup(dev)) {
203 ret = disable_irq_wake(info->id_irq);
204 if (ret)
205 return ret;
206 }
207
208 enable_irq(info->id_irq);
209
210 return ret;
211}
212#endif
213
214static SIMPLE_DEV_PM_OPS(usb_extcon_pm_ops,
215 usb_extcon_suspend, usb_extcon_resume);
216
217static const struct of_device_id usb_extcon_dt_match[] = {
218 { .compatible = "linux,extcon-usb-gpio", },
219 { /* sentinel */ }
220};
221MODULE_DEVICE_TABLE(of, usb_extcon_dt_match);
222
223static struct platform_driver usb_extcon_driver = {
224 .probe = usb_extcon_probe,
225 .remove = usb_extcon_remove,
226 .driver = {
227 .name = "extcon-usb-gpio",
228 .pm = &usb_extcon_pm_ops,
229 .of_match_table = usb_extcon_dt_match,
230 },
231};
232
233module_platform_driver(usb_extcon_driver);
234
235MODULE_AUTHOR("Roger Quadros <rogerq@ti.com>");
236MODULE_DESCRIPTION("USB GPIO extcon driver");
237MODULE_LICENSE("GPL v2");
diff --git a/drivers/extcon/extcon-class.c b/drivers/extcon/extcon.c
index 8319f25b7145..4c9f165e4a04 100644
--- a/drivers/extcon/extcon-class.c
+++ b/drivers/extcon/extcon.c
@@ -158,6 +158,7 @@ static ssize_t name_show(struct device *dev, struct device_attribute *attr,
158 /* Optional callback given by the user */ 158 /* Optional callback given by the user */
159 if (edev->print_name) { 159 if (edev->print_name) {
160 int ret = edev->print_name(edev, buf); 160 int ret = edev->print_name(edev, buf);
161
161 if (ret >= 0) 162 if (ret >= 0)
162 return ret; 163 return ret;
163 } 164 }
@@ -444,6 +445,9 @@ int extcon_register_interest(struct extcon_specific_cable_nb *obj,
444 const char *extcon_name, const char *cable_name, 445 const char *extcon_name, const char *cable_name,
445 struct notifier_block *nb) 446 struct notifier_block *nb)
446{ 447{
448 unsigned long flags;
449 int ret;
450
447 if (!obj || !cable_name || !nb) 451 if (!obj || !cable_name || !nb)
448 return -EINVAL; 452 return -EINVAL;
449 453
@@ -461,8 +465,11 @@ int extcon_register_interest(struct extcon_specific_cable_nb *obj,
461 465
462 obj->internal_nb.notifier_call = _call_per_cable; 466 obj->internal_nb.notifier_call = _call_per_cable;
463 467
464 return raw_notifier_chain_register(&obj->edev->nh, 468 spin_lock_irqsave(&obj->edev->lock, flags);
469 ret = raw_notifier_chain_register(&obj->edev->nh,
465 &obj->internal_nb); 470 &obj->internal_nb);
471 spin_unlock_irqrestore(&obj->edev->lock, flags);
472 return ret;
466 } else { 473 } else {
467 struct class_dev_iter iter; 474 struct class_dev_iter iter;
468 struct extcon_dev *extd; 475 struct extcon_dev *extd;
@@ -495,10 +502,17 @@ EXPORT_SYMBOL_GPL(extcon_register_interest);
495 */ 502 */
496int extcon_unregister_interest(struct extcon_specific_cable_nb *obj) 503int extcon_unregister_interest(struct extcon_specific_cable_nb *obj)
497{ 504{
505 unsigned long flags;
506 int ret;
507
498 if (!obj) 508 if (!obj)
499 return -EINVAL; 509 return -EINVAL;
500 510
501 return raw_notifier_chain_unregister(&obj->edev->nh, &obj->internal_nb); 511 spin_lock_irqsave(&obj->edev->lock, flags);
512 ret = raw_notifier_chain_unregister(&obj->edev->nh, &obj->internal_nb);
513 spin_unlock_irqrestore(&obj->edev->lock, flags);
514
515 return ret;
502} 516}
503EXPORT_SYMBOL_GPL(extcon_unregister_interest); 517EXPORT_SYMBOL_GPL(extcon_unregister_interest);
504 518
@@ -515,7 +529,14 @@ EXPORT_SYMBOL_GPL(extcon_unregister_interest);
515int extcon_register_notifier(struct extcon_dev *edev, 529int extcon_register_notifier(struct extcon_dev *edev,
516 struct notifier_block *nb) 530 struct notifier_block *nb)
517{ 531{
518 return raw_notifier_chain_register(&edev->nh, nb); 532 unsigned long flags;
533 int ret;
534
535 spin_lock_irqsave(&edev->lock, flags);
536 ret = raw_notifier_chain_register(&edev->nh, nb);
537 spin_unlock_irqrestore(&edev->lock, flags);
538
539 return ret;
519} 540}
520EXPORT_SYMBOL_GPL(extcon_register_notifier); 541EXPORT_SYMBOL_GPL(extcon_register_notifier);
521 542
@@ -527,7 +548,14 @@ EXPORT_SYMBOL_GPL(extcon_register_notifier);
527int extcon_unregister_notifier(struct extcon_dev *edev, 548int extcon_unregister_notifier(struct extcon_dev *edev,
528 struct notifier_block *nb) 549 struct notifier_block *nb)
529{ 550{
530 return raw_notifier_chain_unregister(&edev->nh, nb); 551 unsigned long flags;
552 int ret;
553
554 spin_lock_irqsave(&edev->lock, flags);
555 ret = raw_notifier_chain_unregister(&edev->nh, nb);
556 spin_unlock_irqrestore(&edev->lock, flags);
557
558 return ret;
531} 559}
532EXPORT_SYMBOL_GPL(extcon_unregister_notifier); 560EXPORT_SYMBOL_GPL(extcon_unregister_notifier);
533 561
diff --git a/include/linux/mfd/arizona/core.h b/include/linux/mfd/arizona/core.h
index 910e3aa1e965..4863548faff7 100644
--- a/include/linux/mfd/arizona/core.h
+++ b/include/linux/mfd/arizona/core.h
@@ -126,7 +126,7 @@ struct arizona {
126 struct regmap_irq_chip_data *aod_irq_chip; 126 struct regmap_irq_chip_data *aod_irq_chip;
127 struct regmap_irq_chip_data *irq_chip; 127 struct regmap_irq_chip_data *irq_chip;
128 128
129 bool hpdet_magic; 129 bool hpdet_clamp;
130 unsigned int hp_ena; 130 unsigned int hp_ena;
131 131
132 struct mutex clk_lock; 132 struct mutex clk_lock;
diff --git a/sound/soc/codecs/arizona.c b/sound/soc/codecs/arizona.c
index 29202610dd0d..fb58c7ee3780 100644
--- a/sound/soc/codecs/arizona.c
+++ b/sound/soc/codecs/arizona.c
@@ -840,8 +840,8 @@ int arizona_hp_ev(struct snd_soc_dapm_widget *w,
840 priv->arizona->hp_ena &= ~mask; 840 priv->arizona->hp_ena &= ~mask;
841 priv->arizona->hp_ena |= val; 841 priv->arizona->hp_ena |= val;
842 842
843 /* Force off if HPDET magic is active */ 843 /* Force off if HPDET clamp is active */
844 if (priv->arizona->hpdet_magic) 844 if (priv->arizona->hpdet_clamp)
845 val = 0; 845 val = 0;
846 846
847 regmap_update_bits_async(arizona->regmap, ARIZONA_OUTPUT_ENABLES_1, 847 regmap_update_bits_async(arizona->regmap, ARIZONA_OUTPUT_ENABLES_1,