diff options
author | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2014-07-28 02:11:14 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2014-07-28 02:11:14 -0400 |
commit | 16eb2bfc65ef86d3ac6420d50ddc2c48f0023cee (patch) | |
tree | 50f0163f007a90b0c8fcb2e5651cfbb5d6ed0596 | |
parent | 7b9d1f0b7a18b86db0ac1de628fa91c0994fefbe (diff) | |
parent | d3b503140e15d302bc55cf5a90226f0f85860bc2 (diff) |
Merge tag 'extcon-next-for-3.17' of git://git.kernel.org/pub/scm/linux/kernel/git/chanwoo/extcon into char-misc-next
Chanwoo writes:
Update extcon for v3.17
This patchset add new extcon provider driver and fix minor issue of extcon driver.
Detailed description for patchset:
1. Add new Silicon-Mitus SM5502 MUIC (Micro-USB Interface Controller) device
- extcon-sm5502 driver is capable of identifying the type of the external power
source and attached accessory. And external power sources, such as Dedicated
charger or a standard USB port, are able to charge the battery in the smart
phone via the connector.
2. Fix minor issue of extcon driver
- extcon-arizona driver
- extcon-palmas driver
- Remove unnecessary OOM messages for all extcon device drivers
3. Fix minor issue of extcon core
- Re-order the sequence of extcon device driver in Kconfig/Makefile alphabitically
- Set parent device of extcon device automatically using devm_extcon_dev_allocate()
4. Fix MAX77693 driver
- This patchset has dependency on MFD/Regulator/Extcon. So, Lee Jones
(MFD Maintainer) created Immutable branch between MFD and Extcon due
for v3.17 merge-window and then I merged this patchset from MFD git repo[1]
to Extcon git repo.
[1] git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd
(branch: ib-mfd-extcon-regulator)
-rw-r--r-- | Documentation/devicetree/bindings/extcon/extcon-sm5502.txt | 23 | ||||
-rw-r--r-- | drivers/extcon/Kconfig | 38 | ||||
-rw-r--r-- | drivers/extcon/Makefile | 7 | ||||
-rw-r--r-- | drivers/extcon/extcon-adc-jack.c | 1 | ||||
-rw-r--r-- | drivers/extcon/extcon-arizona.c | 74 | ||||
-rw-r--r-- | drivers/extcon/extcon-class.c | 2 | ||||
-rw-r--r-- | drivers/extcon/extcon-gpio.c | 1 | ||||
-rw-r--r-- | drivers/extcon/extcon-max14577.c | 5 | ||||
-rw-r--r-- | drivers/extcon/extcon-max77693.c | 41 | ||||
-rw-r--r-- | drivers/extcon/extcon-max8997.c | 5 | ||||
-rw-r--r-- | drivers/extcon/extcon-palmas.c | 3 | ||||
-rw-r--r-- | drivers/extcon/extcon-sm5502.c | 724 | ||||
-rw-r--r-- | drivers/mfd/Kconfig | 1 | ||||
-rw-r--r-- | drivers/mfd/Makefile | 2 | ||||
-rw-r--r-- | drivers/mfd/max77693-irq.c | 336 | ||||
-rw-r--r-- | drivers/mfd/max77693.c | 210 | ||||
-rw-r--r-- | drivers/regulator/max77693.c | 12 | ||||
-rw-r--r-- | include/linux/extcon/sm5502.h | 287 | ||||
-rw-r--r-- | include/linux/mfd/arizona/pdata.h | 3 | ||||
-rw-r--r-- | include/linux/mfd/max77693-private.h | 54 |
20 files changed, 1335 insertions, 494 deletions
diff --git a/Documentation/devicetree/bindings/extcon/extcon-sm5502.txt b/Documentation/devicetree/bindings/extcon/extcon-sm5502.txt new file mode 100644 index 000000000000..4ecda224955f --- /dev/null +++ b/Documentation/devicetree/bindings/extcon/extcon-sm5502.txt | |||
@@ -0,0 +1,23 @@ | |||
1 | |||
2 | * SM5502 MUIC (Micro-USB Interface Controller) device | ||
3 | |||
4 | The Silicon Mitus SM5502 is a MUIC (Micro-USB Interface Controller) device | ||
5 | which can detect the state of external accessory when external accessory is | ||
6 | attached or detached and button is pressed or released. It is interfaced to | ||
7 | the host controller using an I2C interface. | ||
8 | |||
9 | Required properties: | ||
10 | - compatible: Should be "siliconmitus,sm5502-muic" | ||
11 | - reg: Specifies the I2C slave address of the MUIC block. It should be 0x25 | ||
12 | - interrupt-parent: Specifies the phandle of the interrupt controller to which | ||
13 | the interrupts from sm5502 are delivered to. | ||
14 | - interrupts: Interrupt specifiers for detection interrupt sources. | ||
15 | |||
16 | Example: | ||
17 | |||
18 | sm5502@25 { | ||
19 | compatible = "siliconmitus,sm5502-muic"; | ||
20 | interrupt-parent = <&gpx1>; | ||
21 | interrupts = <5 0>; | ||
22 | reg = <0x25>; | ||
23 | }; | ||
diff --git a/drivers/extcon/Kconfig b/drivers/extcon/Kconfig index aebde489c291..6f2f4727de2c 100644 --- a/drivers/extcon/Kconfig +++ b/drivers/extcon/Kconfig | |||
@@ -14,6 +14,20 @@ if EXTCON | |||
14 | 14 | ||
15 | comment "Extcon Device Drivers" | 15 | comment "Extcon Device Drivers" |
16 | 16 | ||
17 | config EXTCON_ADC_JACK | ||
18 | tristate "ADC Jack extcon support" | ||
19 | depends on IIO | ||
20 | help | ||
21 | Say Y here to enable extcon device driver based on ADC values. | ||
22 | |||
23 | config EXTCON_ARIZONA | ||
24 | tristate "Wolfson Arizona EXTCON support" | ||
25 | depends on MFD_ARIZONA && INPUT && SND_SOC | ||
26 | help | ||
27 | Say Y here to enable support for external accessory detection | ||
28 | with Wolfson Arizona devices. These are audio CODECs with | ||
29 | advanced audio accessory detection support. | ||
30 | |||
17 | config EXTCON_GPIO | 31 | config EXTCON_GPIO |
18 | tristate "GPIO extcon support" | 32 | tristate "GPIO extcon support" |
19 | depends on GPIOLIB | 33 | depends on GPIOLIB |
@@ -21,12 +35,6 @@ config EXTCON_GPIO | |||
21 | Say Y here to enable GPIO based extcon support. Note that GPIO | 35 | Say Y here to enable GPIO based extcon support. Note that GPIO |
22 | extcon supports single state per extcon instance. | 36 | extcon supports single state per extcon instance. |
23 | 37 | ||
24 | config EXTCON_ADC_JACK | ||
25 | tristate "ADC Jack extcon support" | ||
26 | depends on IIO | ||
27 | help | ||
28 | Say Y here to enable extcon device driver based on ADC values. | ||
29 | |||
30 | config EXTCON_MAX14577 | 38 | config EXTCON_MAX14577 |
31 | tristate "MAX14577/77836 EXTCON Support" | 39 | tristate "MAX14577/77836 EXTCON Support" |
32 | depends on MFD_MAX14577 | 40 | depends on MFD_MAX14577 |
@@ -55,14 +63,6 @@ config EXTCON_MAX8997 | |||
55 | Maxim MAX8997 PMIC. The MAX8997 MUIC is a USB port accessory | 63 | Maxim MAX8997 PMIC. The MAX8997 MUIC is a USB port accessory |
56 | detector and switch. | 64 | detector and switch. |
57 | 65 | ||
58 | config EXTCON_ARIZONA | ||
59 | tristate "Wolfson Arizona EXTCON support" | ||
60 | depends on MFD_ARIZONA && INPUT && SND_SOC | ||
61 | help | ||
62 | Say Y here to enable support for external accessory detection | ||
63 | with Wolfson Arizona devices. These are audio CODECs with | ||
64 | advanced audio accessory detection support. | ||
65 | |||
66 | config EXTCON_PALMAS | 66 | config EXTCON_PALMAS |
67 | tristate "Palmas USB EXTCON support" | 67 | tristate "Palmas USB EXTCON support" |
68 | depends on MFD_PALMAS | 68 | depends on MFD_PALMAS |
@@ -70,4 +70,14 @@ config EXTCON_PALMAS | |||
70 | Say Y here to enable support for USB peripheral and USB host | 70 | Say Y here to enable support for USB peripheral and USB host |
71 | detection by palmas usb. | 71 | detection by palmas usb. |
72 | 72 | ||
73 | config EXTCON_SM5502 | ||
74 | tristate "SM5502 EXTCON support" | ||
75 | select IRQ_DOMAIN | ||
76 | select REGMAP_I2C | ||
77 | select REGMAP_IRQ | ||
78 | help | ||
79 | If you say yes here you get support for the MUIC device of | ||
80 | Silicon Mitus SM5502. The SM5502 is a USB port accessory | ||
81 | detector and switch. | ||
82 | |||
73 | endif # MULTISTATE_SWITCH | 83 | endif # MULTISTATE_SWITCH |
diff --git a/drivers/extcon/Makefile b/drivers/extcon/Makefile index bf7861ec0906..b38546eb522a 100644 --- a/drivers/extcon/Makefile +++ b/drivers/extcon/Makefile | |||
@@ -1,12 +1,13 @@ | |||
1 | # | 1 | |
2 | # Makefile for external connector class (extcon) devices | 2 | # Makefile for external connector class (extcon) devices |
3 | # | 3 | # |
4 | 4 | ||
5 | obj-$(CONFIG_EXTCON) += extcon-class.o | 5 | obj-$(CONFIG_EXTCON) += extcon-class.o |
6 | obj-$(CONFIG_EXTCON_GPIO) += extcon-gpio.o | ||
7 | obj-$(CONFIG_EXTCON_ADC_JACK) += extcon-adc-jack.o | 6 | obj-$(CONFIG_EXTCON_ADC_JACK) += extcon-adc-jack.o |
7 | obj-$(CONFIG_EXTCON_ARIZONA) += extcon-arizona.o | ||
8 | obj-$(CONFIG_EXTCON_GPIO) += extcon-gpio.o | ||
8 | obj-$(CONFIG_EXTCON_MAX14577) += extcon-max14577.o | 9 | obj-$(CONFIG_EXTCON_MAX14577) += extcon-max14577.o |
9 | obj-$(CONFIG_EXTCON_MAX77693) += extcon-max77693.o | 10 | obj-$(CONFIG_EXTCON_MAX77693) += extcon-max77693.o |
10 | obj-$(CONFIG_EXTCON_MAX8997) += extcon-max8997.o | 11 | obj-$(CONFIG_EXTCON_MAX8997) += extcon-max8997.o |
11 | obj-$(CONFIG_EXTCON_ARIZONA) += extcon-arizona.o | ||
12 | obj-$(CONFIG_EXTCON_PALMAS) += extcon-palmas.o | 12 | obj-$(CONFIG_EXTCON_PALMAS) += extcon-palmas.o |
13 | obj-$(CONFIG_EXTCON_SM5502) += extcon-sm5502.o | ||
diff --git a/drivers/extcon/extcon-adc-jack.c b/drivers/extcon/extcon-adc-jack.c index e18f95be3733..d860229e4de1 100644 --- a/drivers/extcon/extcon-adc-jack.c +++ b/drivers/extcon/extcon-adc-jack.c | |||
@@ -112,7 +112,6 @@ static int adc_jack_probe(struct platform_device *pdev) | |||
112 | dev_err(&pdev->dev, "failed to allocate extcon device\n"); | 112 | dev_err(&pdev->dev, "failed to allocate extcon device\n"); |
113 | return -ENOMEM; | 113 | return -ENOMEM; |
114 | } | 114 | } |
115 | data->edev->dev.parent = &pdev->dev; | ||
116 | data->edev->name = pdata->name; | 115 | data->edev->name = pdata->name; |
117 | 116 | ||
118 | /* Check the length of array and set num_cables */ | 117 | /* Check the length of array and set num_cables */ |
diff --git a/drivers/extcon/extcon-arizona.c b/drivers/extcon/extcon-arizona.c index 6c84e3d12043..ba51588cc000 100644 --- a/drivers/extcon/extcon-arizona.c +++ b/drivers/extcon/extcon-arizona.c | |||
@@ -39,6 +39,11 @@ | |||
39 | #define ARIZONA_ACCDET_MODE_HPL 1 | 39 | #define ARIZONA_ACCDET_MODE_HPL 1 |
40 | #define ARIZONA_ACCDET_MODE_HPR 2 | 40 | #define ARIZONA_ACCDET_MODE_HPR 2 |
41 | 41 | ||
42 | #define ARIZONA_MICD_CLAMP_MODE_JDL 0x4 | ||
43 | #define ARIZONA_MICD_CLAMP_MODE_JDH 0x5 | ||
44 | #define ARIZONA_MICD_CLAMP_MODE_JDL_GP5H 0x9 | ||
45 | #define ARIZONA_MICD_CLAMP_MODE_JDH_GP5H 0xb | ||
46 | |||
42 | #define ARIZONA_HPDET_MAX 10000 | 47 | #define ARIZONA_HPDET_MAX 10000 |
43 | 48 | ||
44 | #define HPDET_DEBOUNCE 500 | 49 | #define HPDET_DEBOUNCE 500 |
@@ -324,14 +329,17 @@ static void arizona_stop_mic(struct arizona_extcon_info *info) | |||
324 | } | 329 | } |
325 | 330 | ||
326 | static struct { | 331 | static struct { |
332 | unsigned int threshold; | ||
327 | unsigned int factor_a; | 333 | unsigned int factor_a; |
328 | unsigned int factor_b; | 334 | unsigned int factor_b; |
329 | } arizona_hpdet_b_ranges[] = { | 335 | } arizona_hpdet_b_ranges[] = { |
330 | { 5528, 362464 }, | 336 | { 100, 5528, 362464 }, |
331 | { 11084, 6186851 }, | 337 | { 169, 11084, 6186851 }, |
332 | { 11065, 65460395 }, | 338 | { 169, 11065, 65460395 }, |
333 | }; | 339 | }; |
334 | 340 | ||
341 | #define ARIZONA_HPDET_B_RANGE_MAX 0x3fb | ||
342 | |||
335 | static struct { | 343 | static struct { |
336 | int min; | 344 | int min; |
337 | int max; | 345 | int max; |
@@ -386,7 +394,8 @@ static int arizona_hpdet_read(struct arizona_extcon_info *info) | |||
386 | >> ARIZONA_HP_IMPEDANCE_RANGE_SHIFT; | 394 | >> ARIZONA_HP_IMPEDANCE_RANGE_SHIFT; |
387 | 395 | ||
388 | if (range < ARRAY_SIZE(arizona_hpdet_b_ranges) - 1 && | 396 | if (range < ARRAY_SIZE(arizona_hpdet_b_ranges) - 1 && |
389 | (val < 100 || val >= 0x3fb)) { | 397 | (val < arizona_hpdet_b_ranges[range].threshold || |
398 | val >= ARIZONA_HPDET_B_RANGE_MAX)) { | ||
390 | range++; | 399 | range++; |
391 | dev_dbg(arizona->dev, "Moving to HPDET range %d\n", | 400 | dev_dbg(arizona->dev, "Moving to HPDET range %d\n", |
392 | range); | 401 | range); |
@@ -399,7 +408,8 @@ static int arizona_hpdet_read(struct arizona_extcon_info *info) | |||
399 | } | 408 | } |
400 | 409 | ||
401 | /* If we go out of range report top of range */ | 410 | /* If we go out of range report top of range */ |
402 | if (val < 100 || val >= 0x3fb) { | 411 | if (val < arizona_hpdet_b_ranges[range].threshold || |
412 | val >= ARIZONA_HPDET_B_RANGE_MAX) { | ||
403 | dev_dbg(arizona->dev, "Measurement out of range\n"); | 413 | dev_dbg(arizona->dev, "Measurement out of range\n"); |
404 | return ARIZONA_HPDET_MAX; | 414 | return ARIZONA_HPDET_MAX; |
405 | } | 415 | } |
@@ -664,9 +674,8 @@ err: | |||
664 | ARIZONA_ACCDET_MODE_MASK, ARIZONA_ACCDET_MODE_MIC); | 674 | ARIZONA_ACCDET_MODE_MASK, ARIZONA_ACCDET_MODE_MIC); |
665 | 675 | ||
666 | /* Just report headphone */ | 676 | /* Just report headphone */ |
667 | ret = extcon_update_state(info->edev, | 677 | ret = extcon_set_cable_state_(info->edev, |
668 | 1 << ARIZONA_CABLE_HEADPHONE, | 678 | ARIZONA_CABLE_HEADPHONE, true); |
669 | 1 << ARIZONA_CABLE_HEADPHONE); | ||
670 | if (ret != 0) | 679 | if (ret != 0) |
671 | dev_err(arizona->dev, "Failed to report headphone: %d\n", ret); | 680 | dev_err(arizona->dev, "Failed to report headphone: %d\n", ret); |
672 | 681 | ||
@@ -723,9 +732,8 @@ err: | |||
723 | ARIZONA_ACCDET_MODE_MASK, ARIZONA_ACCDET_MODE_MIC); | 732 | ARIZONA_ACCDET_MODE_MASK, ARIZONA_ACCDET_MODE_MIC); |
724 | 733 | ||
725 | /* Just report headphone */ | 734 | /* Just report headphone */ |
726 | ret = extcon_update_state(info->edev, | 735 | ret = extcon_set_cable_state_(info->edev, |
727 | 1 << ARIZONA_CABLE_HEADPHONE, | 736 | ARIZONA_CABLE_HEADPHONE, true); |
728 | 1 << ARIZONA_CABLE_HEADPHONE); | ||
729 | if (ret != 0) | 737 | if (ret != 0) |
730 | dev_err(arizona->dev, "Failed to report headphone: %d\n", ret); | 738 | dev_err(arizona->dev, "Failed to report headphone: %d\n", ret); |
731 | 739 | ||
@@ -812,16 +820,15 @@ static void arizona_micd_detect(struct work_struct *work) | |||
812 | if (info->detecting && (val & ARIZONA_MICD_LVL_8)) { | 820 | if (info->detecting && (val & ARIZONA_MICD_LVL_8)) { |
813 | arizona_identify_headphone(info); | 821 | arizona_identify_headphone(info); |
814 | 822 | ||
815 | ret = extcon_update_state(info->edev, | 823 | ret = extcon_set_cable_state_(info->edev, |
816 | 1 << ARIZONA_CABLE_MICROPHONE, | 824 | ARIZONA_CABLE_MICROPHONE, true); |
817 | 1 << ARIZONA_CABLE_MICROPHONE); | ||
818 | 825 | ||
819 | if (ret != 0) | 826 | if (ret != 0) |
820 | dev_err(arizona->dev, "Headset report failed: %d\n", | 827 | dev_err(arizona->dev, "Headset report failed: %d\n", |
821 | ret); | 828 | ret); |
822 | 829 | ||
823 | /* Don't need to regulate for button detection */ | 830 | /* Don't need to regulate for button detection */ |
824 | ret = regulator_allow_bypass(info->micvdd, false); | 831 | ret = regulator_allow_bypass(info->micvdd, true); |
825 | if (ret != 0) { | 832 | if (ret != 0) { |
826 | dev_err(arizona->dev, "Failed to bypass MICVDD: %d\n", | 833 | dev_err(arizona->dev, "Failed to bypass MICVDD: %d\n", |
827 | ret); | 834 | ret); |
@@ -962,10 +969,16 @@ static irqreturn_t arizona_jackdet(int irq, void *data) | |||
962 | 969 | ||
963 | if (arizona->pdata.jd_gpio5) { | 970 | if (arizona->pdata.jd_gpio5) { |
964 | mask = ARIZONA_MICD_CLAMP_STS; | 971 | mask = ARIZONA_MICD_CLAMP_STS; |
965 | present = 0; | 972 | if (arizona->pdata.jd_invert) |
973 | present = ARIZONA_MICD_CLAMP_STS; | ||
974 | else | ||
975 | present = 0; | ||
966 | } else { | 976 | } else { |
967 | mask = ARIZONA_JD1_STS; | 977 | mask = ARIZONA_JD1_STS; |
968 | present = ARIZONA_JD1_STS; | 978 | if (arizona->pdata.jd_invert) |
979 | present = 0; | ||
980 | else | ||
981 | present = ARIZONA_JD1_STS; | ||
969 | } | 982 | } |
970 | 983 | ||
971 | ret = regmap_read(arizona->regmap, ARIZONA_AOD_IRQ_RAW_STATUS, &val); | 984 | ret = regmap_read(arizona->regmap, ARIZONA_AOD_IRQ_RAW_STATUS, &val); |
@@ -1096,6 +1109,7 @@ static int arizona_extcon_probe(struct platform_device *pdev) | |||
1096 | struct arizona_pdata *pdata = &arizona->pdata; | 1109 | struct arizona_pdata *pdata = &arizona->pdata; |
1097 | struct arizona_extcon_info *info; | 1110 | struct arizona_extcon_info *info; |
1098 | unsigned int val; | 1111 | unsigned int val; |
1112 | unsigned int clamp_mode; | ||
1099 | int jack_irq_fall, jack_irq_rise; | 1113 | int jack_irq_fall, jack_irq_rise; |
1100 | int ret, mode, i, j; | 1114 | int ret, mode, i, j; |
1101 | 1115 | ||
@@ -1103,12 +1117,10 @@ static int arizona_extcon_probe(struct platform_device *pdev) | |||
1103 | return -EPROBE_DEFER; | 1117 | return -EPROBE_DEFER; |
1104 | 1118 | ||
1105 | info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL); | 1119 | info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL); |
1106 | if (!info) { | 1120 | if (!info) |
1107 | dev_err(&pdev->dev, "Failed to allocate memory\n"); | ||
1108 | return -ENOMEM; | 1121 | return -ENOMEM; |
1109 | } | ||
1110 | 1122 | ||
1111 | info->micvdd = devm_regulator_get(arizona->dev, "MICVDD"); | 1123 | info->micvdd = devm_regulator_get(&pdev->dev, "MICVDD"); |
1112 | if (IS_ERR(info->micvdd)) { | 1124 | if (IS_ERR(info->micvdd)) { |
1113 | ret = PTR_ERR(info->micvdd); | 1125 | ret = PTR_ERR(info->micvdd); |
1114 | dev_err(arizona->dev, "Failed to get MICVDD: %d\n", ret); | 1126 | dev_err(arizona->dev, "Failed to get MICVDD: %d\n", ret); |
@@ -1156,7 +1168,6 @@ static int arizona_extcon_probe(struct platform_device *pdev) | |||
1156 | return -ENOMEM; | 1168 | return -ENOMEM; |
1157 | } | 1169 | } |
1158 | info->edev->name = "Headset Jack"; | 1170 | info->edev->name = "Headset Jack"; |
1159 | info->edev->dev.parent = arizona->dev; | ||
1160 | 1171 | ||
1161 | ret = devm_extcon_dev_register(&pdev->dev, info->edev); | 1172 | ret = devm_extcon_dev_register(&pdev->dev, info->edev); |
1162 | if (ret < 0) { | 1173 | if (ret < 0) { |
@@ -1174,7 +1185,6 @@ static int arizona_extcon_probe(struct platform_device *pdev) | |||
1174 | 1185 | ||
1175 | info->input->name = "Headset"; | 1186 | info->input->name = "Headset"; |
1176 | info->input->phys = "arizona/extcon"; | 1187 | info->input->phys = "arizona/extcon"; |
1177 | info->input->dev.parent = &pdev->dev; | ||
1178 | 1188 | ||
1179 | if (pdata->num_micd_configs) { | 1189 | if (pdata->num_micd_configs) { |
1180 | info->micd_modes = pdata->micd_configs; | 1190 | info->micd_modes = pdata->micd_configs; |
@@ -1305,16 +1315,22 @@ static int arizona_extcon_probe(struct platform_device *pdev) | |||
1305 | regmap_write(arizona->regmap, ARIZONA_GPIO5_CTRL, | 1315 | regmap_write(arizona->regmap, ARIZONA_GPIO5_CTRL, |
1306 | val); | 1316 | val); |
1307 | 1317 | ||
1308 | regmap_update_bits(arizona->regmap, | 1318 | if (arizona->pdata.jd_invert) |
1309 | ARIZONA_MICD_CLAMP_CONTROL, | 1319 | clamp_mode = ARIZONA_MICD_CLAMP_MODE_JDH_GP5H; |
1310 | ARIZONA_MICD_CLAMP_MODE_MASK, 0x9); | 1320 | else |
1321 | clamp_mode = ARIZONA_MICD_CLAMP_MODE_JDL_GP5H; | ||
1311 | } else { | 1322 | } else { |
1312 | regmap_update_bits(arizona->regmap, | 1323 | if (arizona->pdata.jd_invert) |
1313 | ARIZONA_MICD_CLAMP_CONTROL, | 1324 | clamp_mode = ARIZONA_MICD_CLAMP_MODE_JDH; |
1314 | ARIZONA_MICD_CLAMP_MODE_MASK, 0x4); | 1325 | else |
1326 | clamp_mode = ARIZONA_MICD_CLAMP_MODE_JDL; | ||
1315 | } | 1327 | } |
1316 | 1328 | ||
1317 | regmap_update_bits(arizona->regmap, | 1329 | regmap_update_bits(arizona->regmap, |
1330 | ARIZONA_MICD_CLAMP_CONTROL, | ||
1331 | ARIZONA_MICD_CLAMP_MODE_MASK, clamp_mode); | ||
1332 | |||
1333 | regmap_update_bits(arizona->regmap, | ||
1318 | ARIZONA_JACK_DETECT_DEBOUNCE, | 1334 | ARIZONA_JACK_DETECT_DEBOUNCE, |
1319 | ARIZONA_MICD_CLAMP_DB, | 1335 | ARIZONA_MICD_CLAMP_DB, |
1320 | ARIZONA_MICD_CLAMP_DB); | 1336 | ARIZONA_MICD_CLAMP_DB); |
diff --git a/drivers/extcon/extcon-class.c b/drivers/extcon/extcon-class.c index 18d42c0e4581..4c2f2c543bb7 100644 --- a/drivers/extcon/extcon-class.c +++ b/drivers/extcon/extcon-class.c | |||
@@ -645,6 +645,8 @@ struct extcon_dev *devm_extcon_dev_allocate(struct device *dev, | |||
645 | return edev; | 645 | return edev; |
646 | } | 646 | } |
647 | 647 | ||
648 | edev->dev.parent = dev; | ||
649 | |||
648 | *ptr = edev; | 650 | *ptr = edev; |
649 | devres_add(dev, ptr); | 651 | devres_add(dev, ptr); |
650 | 652 | ||
diff --git a/drivers/extcon/extcon-gpio.c b/drivers/extcon/extcon-gpio.c index 645b28356819..5b7ec274cb63 100644 --- a/drivers/extcon/extcon-gpio.c +++ b/drivers/extcon/extcon-gpio.c | |||
@@ -105,7 +105,6 @@ static int gpio_extcon_probe(struct platform_device *pdev) | |||
105 | return -ENOMEM; | 105 | return -ENOMEM; |
106 | } | 106 | } |
107 | extcon_data->edev->name = pdata->name; | 107 | extcon_data->edev->name = pdata->name; |
108 | extcon_data->edev->dev.parent = &pdev->dev; | ||
109 | 108 | ||
110 | extcon_data->gpio = pdata->gpio; | 109 | extcon_data->gpio = pdata->gpio; |
111 | extcon_data->gpio_active_low = pdata->gpio_active_low; | 110 | extcon_data->gpio_active_low = pdata->gpio_active_low; |
diff --git a/drivers/extcon/extcon-max14577.c b/drivers/extcon/extcon-max14577.c index d49e891b5675..7309743d0da1 100644 --- a/drivers/extcon/extcon-max14577.c +++ b/drivers/extcon/extcon-max14577.c | |||
@@ -692,10 +692,9 @@ static int max14577_muic_probe(struct platform_device *pdev) | |||
692 | u8 id; | 692 | u8 id; |
693 | 693 | ||
694 | info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL); | 694 | info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL); |
695 | if (!info) { | 695 | if (!info) |
696 | dev_err(&pdev->dev, "failed to allocate memory\n"); | ||
697 | return -ENOMEM; | 696 | return -ENOMEM; |
698 | } | 697 | |
699 | info->dev = &pdev->dev; | 698 | info->dev = &pdev->dev; |
700 | info->max14577 = max14577; | 699 | info->max14577 = max14577; |
701 | 700 | ||
diff --git a/drivers/extcon/extcon-max77693.c b/drivers/extcon/extcon-max77693.c index 2c7c3e191591..77460f2c1ca1 100644 --- a/drivers/extcon/extcon-max77693.c +++ b/drivers/extcon/extcon-max77693.c | |||
@@ -255,10 +255,10 @@ static int max77693_muic_set_debounce_time(struct max77693_muic_info *info, | |||
255 | case ADC_DEBOUNCE_TIME_10MS: | 255 | case ADC_DEBOUNCE_TIME_10MS: |
256 | case ADC_DEBOUNCE_TIME_25MS: | 256 | case ADC_DEBOUNCE_TIME_25MS: |
257 | case ADC_DEBOUNCE_TIME_38_62MS: | 257 | case ADC_DEBOUNCE_TIME_38_62MS: |
258 | ret = max77693_update_reg(info->max77693->regmap_muic, | 258 | ret = regmap_update_bits(info->max77693->regmap_muic, |
259 | MAX77693_MUIC_REG_CTRL3, | 259 | MAX77693_MUIC_REG_CTRL3, |
260 | time << CONTROL3_ADCDBSET_SHIFT, | 260 | CONTROL3_ADCDBSET_MASK, |
261 | CONTROL3_ADCDBSET_MASK); | 261 | time << CONTROL3_ADCDBSET_SHIFT); |
262 | if (ret) { | 262 | if (ret) { |
263 | dev_err(info->dev, "failed to set ADC debounce time\n"); | 263 | dev_err(info->dev, "failed to set ADC debounce time\n"); |
264 | return ret; | 264 | return ret; |
@@ -286,15 +286,15 @@ static int max77693_muic_set_path(struct max77693_muic_info *info, | |||
286 | u8 val, bool attached) | 286 | u8 val, bool attached) |
287 | { | 287 | { |
288 | int ret = 0; | 288 | int ret = 0; |
289 | u8 ctrl1, ctrl2 = 0; | 289 | unsigned int ctrl1, ctrl2 = 0; |
290 | 290 | ||
291 | if (attached) | 291 | if (attached) |
292 | ctrl1 = val; | 292 | ctrl1 = val; |
293 | else | 293 | else |
294 | ctrl1 = CONTROL1_SW_OPEN; | 294 | ctrl1 = CONTROL1_SW_OPEN; |
295 | 295 | ||
296 | ret = max77693_update_reg(info->max77693->regmap_muic, | 296 | ret = regmap_update_bits(info->max77693->regmap_muic, |
297 | MAX77693_MUIC_REG_CTRL1, ctrl1, COMP_SW_MASK); | 297 | MAX77693_MUIC_REG_CTRL1, COMP_SW_MASK, ctrl1); |
298 | if (ret < 0) { | 298 | if (ret < 0) { |
299 | dev_err(info->dev, "failed to update MUIC register\n"); | 299 | dev_err(info->dev, "failed to update MUIC register\n"); |
300 | return ret; | 300 | return ret; |
@@ -305,9 +305,9 @@ static int max77693_muic_set_path(struct max77693_muic_info *info, | |||
305 | else | 305 | else |
306 | ctrl2 |= CONTROL2_LOWPWR_MASK; /* LowPwr=1, CPEn=0 */ | 306 | ctrl2 |= CONTROL2_LOWPWR_MASK; /* LowPwr=1, CPEn=0 */ |
307 | 307 | ||
308 | ret = max77693_update_reg(info->max77693->regmap_muic, | 308 | ret = regmap_update_bits(info->max77693->regmap_muic, |
309 | MAX77693_MUIC_REG_CTRL2, ctrl2, | 309 | MAX77693_MUIC_REG_CTRL2, |
310 | CONTROL2_LOWPWR_MASK | CONTROL2_CPEN_MASK); | 310 | CONTROL2_LOWPWR_MASK | CONTROL2_CPEN_MASK, ctrl2); |
311 | if (ret < 0) { | 311 | if (ret < 0) { |
312 | dev_err(info->dev, "failed to update MUIC register\n"); | 312 | dev_err(info->dev, "failed to update MUIC register\n"); |
313 | return ret; | 313 | return ret; |
@@ -969,8 +969,8 @@ static void max77693_muic_irq_work(struct work_struct *work) | |||
969 | if (info->irq == muic_irqs[i].virq) | 969 | if (info->irq == muic_irqs[i].virq) |
970 | irq_type = muic_irqs[i].irq; | 970 | irq_type = muic_irqs[i].irq; |
971 | 971 | ||
972 | ret = max77693_bulk_read(info->max77693->regmap_muic, | 972 | ret = regmap_bulk_read(info->max77693->regmap_muic, |
973 | MAX77693_MUIC_REG_STATUS1, 2, info->status); | 973 | MAX77693_MUIC_REG_STATUS1, info->status, 2); |
974 | if (ret) { | 974 | if (ret) { |
975 | dev_err(info->dev, "failed to read MUIC register\n"); | 975 | dev_err(info->dev, "failed to read MUIC register\n"); |
976 | mutex_unlock(&info->mutex); | 976 | mutex_unlock(&info->mutex); |
@@ -1042,8 +1042,8 @@ static int max77693_muic_detect_accessory(struct max77693_muic_info *info) | |||
1042 | mutex_lock(&info->mutex); | 1042 | mutex_lock(&info->mutex); |
1043 | 1043 | ||
1044 | /* Read STATUSx register to detect accessory */ | 1044 | /* Read STATUSx register to detect accessory */ |
1045 | ret = max77693_bulk_read(info->max77693->regmap_muic, | 1045 | ret = regmap_bulk_read(info->max77693->regmap_muic, |
1046 | MAX77693_MUIC_REG_STATUS1, 2, info->status); | 1046 | MAX77693_MUIC_REG_STATUS1, info->status, 2); |
1047 | if (ret) { | 1047 | if (ret) { |
1048 | dev_err(info->dev, "failed to read MUIC register\n"); | 1048 | dev_err(info->dev, "failed to read MUIC register\n"); |
1049 | mutex_unlock(&info->mutex); | 1049 | mutex_unlock(&info->mutex); |
@@ -1095,14 +1095,13 @@ static int max77693_muic_probe(struct platform_device *pdev) | |||
1095 | int delay_jiffies; | 1095 | int delay_jiffies; |
1096 | int ret; | 1096 | int ret; |
1097 | int i; | 1097 | int i; |
1098 | u8 id; | 1098 | unsigned int id; |
1099 | 1099 | ||
1100 | info = devm_kzalloc(&pdev->dev, sizeof(struct max77693_muic_info), | 1100 | info = devm_kzalloc(&pdev->dev, sizeof(struct max77693_muic_info), |
1101 | GFP_KERNEL); | 1101 | GFP_KERNEL); |
1102 | if (!info) { | 1102 | if (!info) |
1103 | dev_err(&pdev->dev, "failed to allocate memory\n"); | ||
1104 | return -ENOMEM; | 1103 | return -ENOMEM; |
1105 | } | 1104 | |
1106 | info->dev = &pdev->dev; | 1105 | info->dev = &pdev->dev; |
1107 | info->max77693 = max77693; | 1106 | info->max77693 = max77693; |
1108 | if (info->max77693->regmap_muic) { | 1107 | if (info->max77693->regmap_muic) { |
@@ -1154,7 +1153,8 @@ static int max77693_muic_probe(struct platform_device *pdev) | |||
1154 | struct max77693_muic_irq *muic_irq = &muic_irqs[i]; | 1153 | struct max77693_muic_irq *muic_irq = &muic_irqs[i]; |
1155 | unsigned int virq = 0; | 1154 | unsigned int virq = 0; |
1156 | 1155 | ||
1157 | virq = irq_create_mapping(max77693->irq_domain, muic_irq->irq); | 1156 | virq = regmap_irq_get_virq(max77693->irq_data_muic, |
1157 | muic_irq->irq); | ||
1158 | if (!virq) { | 1158 | if (!virq) { |
1159 | ret = -EINVAL; | 1159 | ret = -EINVAL; |
1160 | goto err_irq; | 1160 | goto err_irq; |
@@ -1183,7 +1183,6 @@ static int max77693_muic_probe(struct platform_device *pdev) | |||
1183 | goto err_irq; | 1183 | goto err_irq; |
1184 | } | 1184 | } |
1185 | info->edev->name = DEV_NAME; | 1185 | info->edev->name = DEV_NAME; |
1186 | info->edev->dev.parent = &pdev->dev; | ||
1187 | 1186 | ||
1188 | ret = devm_extcon_dev_register(&pdev->dev, info->edev); | 1187 | ret = devm_extcon_dev_register(&pdev->dev, info->edev); |
1189 | if (ret) { | 1188 | if (ret) { |
@@ -1204,7 +1203,7 @@ static int max77693_muic_probe(struct platform_device *pdev) | |||
1204 | enum max77693_irq_source irq_src | 1203 | enum max77693_irq_source irq_src |
1205 | = MAX77693_IRQ_GROUP_NR; | 1204 | = MAX77693_IRQ_GROUP_NR; |
1206 | 1205 | ||
1207 | max77693_write_reg(info->max77693->regmap_muic, | 1206 | regmap_write(info->max77693->regmap_muic, |
1208 | init_data[i].addr, | 1207 | init_data[i].addr, |
1209 | init_data[i].data); | 1208 | init_data[i].data); |
1210 | 1209 | ||
@@ -1262,7 +1261,7 @@ static int max77693_muic_probe(struct platform_device *pdev) | |||
1262 | max77693_muic_set_path(info, info->path_uart, true); | 1261 | max77693_muic_set_path(info, info->path_uart, true); |
1263 | 1262 | ||
1264 | /* Check revision number of MUIC device*/ | 1263 | /* Check revision number of MUIC device*/ |
1265 | ret = max77693_read_reg(info->max77693->regmap_muic, | 1264 | ret = regmap_read(info->max77693->regmap_muic, |
1266 | MAX77693_MUIC_REG_ID, &id); | 1265 | MAX77693_MUIC_REG_ID, &id); |
1267 | if (ret < 0) { | 1266 | if (ret < 0) { |
1268 | dev_err(&pdev->dev, "failed to read revision number\n"); | 1267 | dev_err(&pdev->dev, "failed to read revision number\n"); |
diff --git a/drivers/extcon/extcon-max8997.c b/drivers/extcon/extcon-max8997.c index d9f7f1baaa03..75e501c98005 100644 --- a/drivers/extcon/extcon-max8997.c +++ b/drivers/extcon/extcon-max8997.c | |||
@@ -661,10 +661,8 @@ static int max8997_muic_probe(struct platform_device *pdev) | |||
661 | 661 | ||
662 | info = devm_kzalloc(&pdev->dev, sizeof(struct max8997_muic_info), | 662 | info = devm_kzalloc(&pdev->dev, sizeof(struct max8997_muic_info), |
663 | GFP_KERNEL); | 663 | GFP_KERNEL); |
664 | if (!info) { | 664 | if (!info) |
665 | dev_err(&pdev->dev, "failed to allocate memory\n"); | ||
666 | return -ENOMEM; | 665 | return -ENOMEM; |
667 | } | ||
668 | 666 | ||
669 | info->dev = &pdev->dev; | 667 | info->dev = &pdev->dev; |
670 | info->muic = max8997->muic; | 668 | info->muic = max8997->muic; |
@@ -706,7 +704,6 @@ static int max8997_muic_probe(struct platform_device *pdev) | |||
706 | goto err_irq; | 704 | goto err_irq; |
707 | } | 705 | } |
708 | info->edev->name = DEV_NAME; | 706 | info->edev->name = DEV_NAME; |
709 | info->edev->dev.parent = &pdev->dev; | ||
710 | 707 | ||
711 | ret = devm_extcon_dev_register(&pdev->dev, info->edev); | 708 | ret = devm_extcon_dev_register(&pdev->dev, info->edev); |
712 | if (ret) { | 709 | if (ret) { |
diff --git a/drivers/extcon/extcon-palmas.c b/drivers/extcon/extcon-palmas.c index 7417ce84eb2d..230e1220ce48 100644 --- a/drivers/extcon/extcon-palmas.c +++ b/drivers/extcon/extcon-palmas.c | |||
@@ -194,7 +194,6 @@ static int palmas_usb_probe(struct platform_device *pdev) | |||
194 | return -ENOMEM; | 194 | return -ENOMEM; |
195 | } | 195 | } |
196 | palmas_usb->edev->name = kstrdup(node->name, GFP_KERNEL); | 196 | palmas_usb->edev->name = kstrdup(node->name, GFP_KERNEL); |
197 | palmas_usb->edev->dev.parent = palmas_usb->dev; | ||
198 | palmas_usb->edev->mutually_exclusive = mutually_exclusive; | 197 | palmas_usb->edev->mutually_exclusive = mutually_exclusive; |
199 | 198 | ||
200 | status = devm_extcon_dev_register(&pdev->dev, palmas_usb->edev); | 199 | status = devm_extcon_dev_register(&pdev->dev, palmas_usb->edev); |
@@ -278,7 +277,7 @@ static int palmas_usb_resume(struct device *dev) | |||
278 | 277 | ||
279 | static SIMPLE_DEV_PM_OPS(palmas_pm_ops, palmas_usb_suspend, palmas_usb_resume); | 278 | static SIMPLE_DEV_PM_OPS(palmas_pm_ops, palmas_usb_suspend, palmas_usb_resume); |
280 | 279 | ||
281 | static struct of_device_id of_palmas_match_tbl[] = { | 280 | static const struct of_device_id of_palmas_match_tbl[] = { |
282 | { .compatible = "ti,palmas-usb", }, | 281 | { .compatible = "ti,palmas-usb", }, |
283 | { .compatible = "ti,palmas-usb-vid", }, | 282 | { .compatible = "ti,palmas-usb-vid", }, |
284 | { .compatible = "ti,twl6035-usb", }, | 283 | { .compatible = "ti,twl6035-usb", }, |
diff --git a/drivers/extcon/extcon-sm5502.c b/drivers/extcon/extcon-sm5502.c new file mode 100644 index 000000000000..560d7dccec7b --- /dev/null +++ b/drivers/extcon/extcon-sm5502.c | |||
@@ -0,0 +1,724 @@ | |||
1 | /* | ||
2 | * extcon-sm5502.c - Silicon Mitus SM5502 extcon drvier to support USB switches | ||
3 | * | ||
4 | * Copyright (c) 2014 Samsung Electronics Co., Ltd | ||
5 | * Author: Chanwoo Choi <cw00.choi@samsung.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify it | ||
8 | * under the terms of the GNU General Public License as published by the | ||
9 | * Free Software Foundation; either version 2 of the License, or (at your | ||
10 | * option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | */ | ||
17 | |||
18 | #include <linux/err.h> | ||
19 | #include <linux/i2c.h> | ||
20 | #include <linux/input.h> | ||
21 | #include <linux/interrupt.h> | ||
22 | #include <linux/irqdomain.h> | ||
23 | #include <linux/kernel.h> | ||
24 | #include <linux/module.h> | ||
25 | #include <linux/platform_device.h> | ||
26 | #include <linux/regmap.h> | ||
27 | #include <linux/slab.h> | ||
28 | #include <linux/extcon.h> | ||
29 | #include <linux/extcon/sm5502.h> | ||
30 | |||
31 | #define DELAY_MS_DEFAULT 17000 /* unit: millisecond */ | ||
32 | |||
33 | struct muic_irq { | ||
34 | unsigned int irq; | ||
35 | const char *name; | ||
36 | unsigned int virq; | ||
37 | }; | ||
38 | |||
39 | struct reg_data { | ||
40 | u8 reg; | ||
41 | unsigned int val; | ||
42 | bool invert; | ||
43 | }; | ||
44 | |||
45 | struct sm5502_muic_info { | ||
46 | struct device *dev; | ||
47 | struct extcon_dev *edev; | ||
48 | |||
49 | struct i2c_client *i2c; | ||
50 | struct regmap *regmap; | ||
51 | |||
52 | struct regmap_irq_chip_data *irq_data; | ||
53 | struct muic_irq *muic_irqs; | ||
54 | unsigned int num_muic_irqs; | ||
55 | int irq; | ||
56 | bool irq_attach; | ||
57 | bool irq_detach; | ||
58 | struct work_struct irq_work; | ||
59 | |||
60 | struct reg_data *reg_data; | ||
61 | unsigned int num_reg_data; | ||
62 | |||
63 | struct mutex mutex; | ||
64 | |||
65 | /* | ||
66 | * Use delayed workqueue to detect cable state and then | ||
67 | * notify cable state to notifiee/platform through uevent. | ||
68 | * After completing the booting of platform, the extcon provider | ||
69 | * driver should notify cable state to upper layer. | ||
70 | */ | ||
71 | struct delayed_work wq_detcable; | ||
72 | }; | ||
73 | |||
74 | /* Default value of SM5502 register to bring up MUIC device. */ | ||
75 | static struct reg_data sm5502_reg_data[] = { | ||
76 | { | ||
77 | .reg = SM5502_REG_CONTROL, | ||
78 | .val = SM5502_REG_CONTROL_MASK_INT_MASK, | ||
79 | .invert = false, | ||
80 | }, { | ||
81 | .reg = SM5502_REG_INTMASK1, | ||
82 | .val = SM5502_REG_INTM1_KP_MASK | ||
83 | | SM5502_REG_INTM1_LKP_MASK | ||
84 | | SM5502_REG_INTM1_LKR_MASK, | ||
85 | .invert = true, | ||
86 | }, { | ||
87 | .reg = SM5502_REG_INTMASK2, | ||
88 | .val = SM5502_REG_INTM2_VBUS_DET_MASK | ||
89 | | SM5502_REG_INTM2_REV_ACCE_MASK | ||
90 | | SM5502_REG_INTM2_ADC_CHG_MASK | ||
91 | | SM5502_REG_INTM2_STUCK_KEY_MASK | ||
92 | | SM5502_REG_INTM2_STUCK_KEY_RCV_MASK | ||
93 | | SM5502_REG_INTM2_MHL_MASK, | ||
94 | .invert = true, | ||
95 | }, | ||
96 | { } | ||
97 | }; | ||
98 | |||
99 | /* List of detectable cables */ | ||
100 | enum { | ||
101 | EXTCON_CABLE_USB = 0, | ||
102 | EXTCON_CABLE_USB_HOST, | ||
103 | EXTCON_CABLE_TA, | ||
104 | |||
105 | EXTCON_CABLE_END, | ||
106 | }; | ||
107 | |||
108 | static const char *sm5502_extcon_cable[] = { | ||
109 | [EXTCON_CABLE_USB] = "USB", | ||
110 | [EXTCON_CABLE_USB_HOST] = "USB-Host", | ||
111 | [EXTCON_CABLE_TA] = "TA", | ||
112 | NULL, | ||
113 | }; | ||
114 | |||
115 | /* Define supported accessory type */ | ||
116 | enum sm5502_muic_acc_type { | ||
117 | SM5502_MUIC_ADC_GROUND = 0x0, | ||
118 | SM5502_MUIC_ADC_SEND_END_BUTTON, | ||
119 | SM5502_MUIC_ADC_REMOTE_S1_BUTTON, | ||
120 | SM5502_MUIC_ADC_REMOTE_S2_BUTTON, | ||
121 | SM5502_MUIC_ADC_REMOTE_S3_BUTTON, | ||
122 | SM5502_MUIC_ADC_REMOTE_S4_BUTTON, | ||
123 | SM5502_MUIC_ADC_REMOTE_S5_BUTTON, | ||
124 | SM5502_MUIC_ADC_REMOTE_S6_BUTTON, | ||
125 | SM5502_MUIC_ADC_REMOTE_S7_BUTTON, | ||
126 | SM5502_MUIC_ADC_REMOTE_S8_BUTTON, | ||
127 | SM5502_MUIC_ADC_REMOTE_S9_BUTTON, | ||
128 | SM5502_MUIC_ADC_REMOTE_S10_BUTTON, | ||
129 | SM5502_MUIC_ADC_REMOTE_S11_BUTTON, | ||
130 | SM5502_MUIC_ADC_REMOTE_S12_BUTTON, | ||
131 | SM5502_MUIC_ADC_RESERVED_ACC_1, | ||
132 | SM5502_MUIC_ADC_RESERVED_ACC_2, | ||
133 | SM5502_MUIC_ADC_RESERVED_ACC_3, | ||
134 | SM5502_MUIC_ADC_RESERVED_ACC_4, | ||
135 | SM5502_MUIC_ADC_RESERVED_ACC_5, | ||
136 | SM5502_MUIC_ADC_AUDIO_TYPE2, | ||
137 | SM5502_MUIC_ADC_PHONE_POWERED_DEV, | ||
138 | SM5502_MUIC_ADC_TTY_CONVERTER, | ||
139 | SM5502_MUIC_ADC_UART_CABLE, | ||
140 | SM5502_MUIC_ADC_TYPE1_CHARGER, | ||
141 | SM5502_MUIC_ADC_FACTORY_MODE_BOOT_OFF_USB, | ||
142 | SM5502_MUIC_ADC_FACTORY_MODE_BOOT_ON_USB, | ||
143 | SM5502_MUIC_ADC_AUDIO_VIDEO_CABLE, | ||
144 | SM5502_MUIC_ADC_TYPE2_CHARGER, | ||
145 | SM5502_MUIC_ADC_FACTORY_MODE_BOOT_OFF_UART, | ||
146 | SM5502_MUIC_ADC_FACTORY_MODE_BOOT_ON_UART, | ||
147 | SM5502_MUIC_ADC_AUDIO_TYPE1, | ||
148 | SM5502_MUIC_ADC_OPEN = 0x1f, | ||
149 | |||
150 | /* The below accessories have same ADC value (0x1f or 0x1e). | ||
151 | So, Device type1 is used to separate specific accessory. */ | ||
152 | /* |---------|--ADC| */ | ||
153 | /* | [7:5]|[4:0]| */ | ||
154 | SM5502_MUIC_ADC_AUDIO_TYPE1_FULL_REMOTE = 0x3e, /* | 001|11110| */ | ||
155 | SM5502_MUIC_ADC_AUDIO_TYPE1_SEND_END = 0x5e, /* | 010|11110| */ | ||
156 | /* |Dev Type1|--ADC| */ | ||
157 | SM5502_MUIC_ADC_OPEN_USB = 0x5f, /* | 010|11111| */ | ||
158 | SM5502_MUIC_ADC_OPEN_TA = 0xdf, /* | 110|11111| */ | ||
159 | SM5502_MUIC_ADC_OPEN_USB_OTG = 0xff, /* | 111|11111| */ | ||
160 | }; | ||
161 | |||
162 | /* List of supported interrupt for SM5502 */ | ||
163 | static struct muic_irq sm5502_muic_irqs[] = { | ||
164 | { SM5502_IRQ_INT1_ATTACH, "muic-attach" }, | ||
165 | { SM5502_IRQ_INT1_DETACH, "muic-detach" }, | ||
166 | { SM5502_IRQ_INT1_KP, "muic-kp" }, | ||
167 | { SM5502_IRQ_INT1_LKP, "muic-lkp" }, | ||
168 | { SM5502_IRQ_INT1_LKR, "muic-lkr" }, | ||
169 | { SM5502_IRQ_INT1_OVP_EVENT, "muic-ovp-event" }, | ||
170 | { SM5502_IRQ_INT1_OCP_EVENT, "muic-ocp-event" }, | ||
171 | { SM5502_IRQ_INT1_OVP_OCP_DIS, "muic-ovp-ocp-dis" }, | ||
172 | { SM5502_IRQ_INT2_VBUS_DET, "muic-vbus-det" }, | ||
173 | { SM5502_IRQ_INT2_REV_ACCE, "muic-rev-acce" }, | ||
174 | { SM5502_IRQ_INT2_ADC_CHG, "muic-adc-chg" }, | ||
175 | { SM5502_IRQ_INT2_STUCK_KEY, "muic-stuck-key" }, | ||
176 | { SM5502_IRQ_INT2_STUCK_KEY_RCV, "muic-stuck-key-rcv" }, | ||
177 | { SM5502_IRQ_INT2_MHL, "muic-mhl" }, | ||
178 | }; | ||
179 | |||
180 | /* Define interrupt list of SM5502 to register regmap_irq */ | ||
181 | static const struct regmap_irq sm5502_irqs[] = { | ||
182 | /* INT1 interrupts */ | ||
183 | { .reg_offset = 0, .mask = SM5502_IRQ_INT1_ATTACH_MASK, }, | ||
184 | { .reg_offset = 0, .mask = SM5502_IRQ_INT1_DETACH_MASK, }, | ||
185 | { .reg_offset = 0, .mask = SM5502_IRQ_INT1_KP_MASK, }, | ||
186 | { .reg_offset = 0, .mask = SM5502_IRQ_INT1_LKP_MASK, }, | ||
187 | { .reg_offset = 0, .mask = SM5502_IRQ_INT1_LKR_MASK, }, | ||
188 | { .reg_offset = 0, .mask = SM5502_IRQ_INT1_OVP_EVENT_MASK, }, | ||
189 | { .reg_offset = 0, .mask = SM5502_IRQ_INT1_OCP_EVENT_MASK, }, | ||
190 | { .reg_offset = 0, .mask = SM5502_IRQ_INT1_OVP_OCP_DIS_MASK, }, | ||
191 | |||
192 | /* INT2 interrupts */ | ||
193 | { .reg_offset = 1, .mask = SM5502_IRQ_INT2_VBUS_DET_MASK,}, | ||
194 | { .reg_offset = 1, .mask = SM5502_IRQ_INT2_REV_ACCE_MASK, }, | ||
195 | { .reg_offset = 1, .mask = SM5502_IRQ_INT2_ADC_CHG_MASK, }, | ||
196 | { .reg_offset = 1, .mask = SM5502_IRQ_INT2_STUCK_KEY_MASK, }, | ||
197 | { .reg_offset = 1, .mask = SM5502_IRQ_INT2_STUCK_KEY_RCV_MASK, }, | ||
198 | { .reg_offset = 1, .mask = SM5502_IRQ_INT2_MHL_MASK, }, | ||
199 | }; | ||
200 | |||
201 | static const struct regmap_irq_chip sm5502_muic_irq_chip = { | ||
202 | .name = "sm5502", | ||
203 | .status_base = SM5502_REG_INT1, | ||
204 | .mask_base = SM5502_REG_INTMASK1, | ||
205 | .mask_invert = false, | ||
206 | .num_regs = 2, | ||
207 | .irqs = sm5502_irqs, | ||
208 | .num_irqs = ARRAY_SIZE(sm5502_irqs), | ||
209 | }; | ||
210 | |||
211 | /* Define regmap configuration of SM5502 for I2C communication */ | ||
212 | static bool sm5502_muic_volatile_reg(struct device *dev, unsigned int reg) | ||
213 | { | ||
214 | switch (reg) { | ||
215 | case SM5502_REG_INTMASK1: | ||
216 | case SM5502_REG_INTMASK2: | ||
217 | return true; | ||
218 | default: | ||
219 | break; | ||
220 | } | ||
221 | return false; | ||
222 | } | ||
223 | |||
224 | static const struct regmap_config sm5502_muic_regmap_config = { | ||
225 | .reg_bits = 8, | ||
226 | .val_bits = 8, | ||
227 | .volatile_reg = sm5502_muic_volatile_reg, | ||
228 | .max_register = SM5502_REG_END, | ||
229 | }; | ||
230 | |||
231 | /* Change DM_CON/DP_CON/VBUSIN switch according to cable type */ | ||
232 | static int sm5502_muic_set_path(struct sm5502_muic_info *info, | ||
233 | unsigned int con_sw, unsigned int vbus_sw, | ||
234 | bool attached) | ||
235 | { | ||
236 | int ret; | ||
237 | |||
238 | if (!attached) { | ||
239 | con_sw = DM_DP_SWITCH_OPEN; | ||
240 | vbus_sw = VBUSIN_SWITCH_OPEN; | ||
241 | } | ||
242 | |||
243 | switch (con_sw) { | ||
244 | case DM_DP_SWITCH_OPEN: | ||
245 | case DM_DP_SWITCH_USB: | ||
246 | case DM_DP_SWITCH_AUDIO: | ||
247 | case DM_DP_SWITCH_UART: | ||
248 | ret = regmap_update_bits(info->regmap, SM5502_REG_MANUAL_SW1, | ||
249 | SM5502_REG_MANUAL_SW1_DP_MASK | | ||
250 | SM5502_REG_MANUAL_SW1_DM_MASK, | ||
251 | con_sw); | ||
252 | if (ret < 0) { | ||
253 | dev_err(info->dev, | ||
254 | "cannot update DM_CON/DP_CON switch\n"); | ||
255 | return ret; | ||
256 | } | ||
257 | break; | ||
258 | default: | ||
259 | dev_err(info->dev, "Unknown DM_CON/DP_CON switch type (%d)\n", | ||
260 | con_sw); | ||
261 | return -EINVAL; | ||
262 | }; | ||
263 | |||
264 | switch (vbus_sw) { | ||
265 | case VBUSIN_SWITCH_OPEN: | ||
266 | case VBUSIN_SWITCH_VBUSOUT: | ||
267 | case VBUSIN_SWITCH_MIC: | ||
268 | case VBUSIN_SWITCH_VBUSOUT_WITH_USB: | ||
269 | ret = regmap_update_bits(info->regmap, SM5502_REG_MANUAL_SW1, | ||
270 | SM5502_REG_MANUAL_SW1_VBUSIN_MASK, | ||
271 | vbus_sw); | ||
272 | if (ret < 0) { | ||
273 | dev_err(info->dev, | ||
274 | "cannot update VBUSIN switch\n"); | ||
275 | return ret; | ||
276 | } | ||
277 | break; | ||
278 | default: | ||
279 | dev_err(info->dev, "Unknown VBUS switch type (%d)\n", vbus_sw); | ||
280 | return -EINVAL; | ||
281 | }; | ||
282 | |||
283 | return 0; | ||
284 | } | ||
285 | |||
286 | /* Return cable type of attached or detached accessories */ | ||
287 | static unsigned int sm5502_muic_get_cable_type(struct sm5502_muic_info *info) | ||
288 | { | ||
289 | unsigned int cable_type = -1, adc, dev_type1; | ||
290 | int ret; | ||
291 | |||
292 | /* Read ADC value according to external cable or button */ | ||
293 | ret = regmap_read(info->regmap, SM5502_REG_ADC, &adc); | ||
294 | if (ret) { | ||
295 | dev_err(info->dev, "failed to read ADC register\n"); | ||
296 | return ret; | ||
297 | } | ||
298 | |||
299 | /* | ||
300 | * If ADC is SM5502_MUIC_ADC_GROUND(0x0), external cable hasn't | ||
301 | * connected with to MUIC device. | ||
302 | */ | ||
303 | cable_type &= SM5502_REG_ADC_MASK; | ||
304 | if (cable_type == SM5502_MUIC_ADC_GROUND) | ||
305 | return SM5502_MUIC_ADC_GROUND; | ||
306 | |||
307 | switch (cable_type) { | ||
308 | case SM5502_MUIC_ADC_GROUND: | ||
309 | case SM5502_MUIC_ADC_SEND_END_BUTTON: | ||
310 | case SM5502_MUIC_ADC_REMOTE_S1_BUTTON: | ||
311 | case SM5502_MUIC_ADC_REMOTE_S2_BUTTON: | ||
312 | case SM5502_MUIC_ADC_REMOTE_S3_BUTTON: | ||
313 | case SM5502_MUIC_ADC_REMOTE_S4_BUTTON: | ||
314 | case SM5502_MUIC_ADC_REMOTE_S5_BUTTON: | ||
315 | case SM5502_MUIC_ADC_REMOTE_S6_BUTTON: | ||
316 | case SM5502_MUIC_ADC_REMOTE_S7_BUTTON: | ||
317 | case SM5502_MUIC_ADC_REMOTE_S8_BUTTON: | ||
318 | case SM5502_MUIC_ADC_REMOTE_S9_BUTTON: | ||
319 | case SM5502_MUIC_ADC_REMOTE_S10_BUTTON: | ||
320 | case SM5502_MUIC_ADC_REMOTE_S11_BUTTON: | ||
321 | case SM5502_MUIC_ADC_REMOTE_S12_BUTTON: | ||
322 | case SM5502_MUIC_ADC_RESERVED_ACC_1: | ||
323 | case SM5502_MUIC_ADC_RESERVED_ACC_2: | ||
324 | case SM5502_MUIC_ADC_RESERVED_ACC_3: | ||
325 | case SM5502_MUIC_ADC_RESERVED_ACC_4: | ||
326 | case SM5502_MUIC_ADC_RESERVED_ACC_5: | ||
327 | case SM5502_MUIC_ADC_AUDIO_TYPE2: | ||
328 | case SM5502_MUIC_ADC_PHONE_POWERED_DEV: | ||
329 | case SM5502_MUIC_ADC_TTY_CONVERTER: | ||
330 | case SM5502_MUIC_ADC_UART_CABLE: | ||
331 | case SM5502_MUIC_ADC_TYPE1_CHARGER: | ||
332 | case SM5502_MUIC_ADC_FACTORY_MODE_BOOT_OFF_USB: | ||
333 | case SM5502_MUIC_ADC_FACTORY_MODE_BOOT_ON_USB: | ||
334 | case SM5502_MUIC_ADC_AUDIO_VIDEO_CABLE: | ||
335 | case SM5502_MUIC_ADC_TYPE2_CHARGER: | ||
336 | case SM5502_MUIC_ADC_FACTORY_MODE_BOOT_OFF_UART: | ||
337 | case SM5502_MUIC_ADC_FACTORY_MODE_BOOT_ON_UART: | ||
338 | break; | ||
339 | case SM5502_MUIC_ADC_AUDIO_TYPE1: | ||
340 | /* | ||
341 | * Check whether cable type is | ||
342 | * SM5502_MUIC_ADC_AUDIO_TYPE1_FULL_REMOTE | ||
343 | * or SM5502_MUIC_ADC_AUDIO_TYPE1_SEND_END | ||
344 | * by using Button event. | ||
345 | */ | ||
346 | break; | ||
347 | case SM5502_MUIC_ADC_OPEN: | ||
348 | ret = regmap_read(info->regmap, SM5502_REG_DEV_TYPE1, | ||
349 | &dev_type1); | ||
350 | if (ret) { | ||
351 | dev_err(info->dev, "failed to read DEV_TYPE1 reg\n"); | ||
352 | return ret; | ||
353 | } | ||
354 | |||
355 | switch (dev_type1) { | ||
356 | case SM5502_REG_DEV_TYPE1_USB_SDP_MASK: | ||
357 | cable_type = SM5502_MUIC_ADC_OPEN_USB; | ||
358 | break; | ||
359 | case SM5502_REG_DEV_TYPE1_DEDICATED_CHG_MASK: | ||
360 | cable_type = SM5502_MUIC_ADC_OPEN_TA; | ||
361 | break; | ||
362 | case SM5502_REG_DEV_TYPE1_USB_OTG_MASK: | ||
363 | cable_type = SM5502_MUIC_ADC_OPEN_USB_OTG; | ||
364 | break; | ||
365 | default: | ||
366 | dev_dbg(info->dev, | ||
367 | "cannot identify the cable type: adc(0x%x) " | ||
368 | "dev_type1(0x%x)\n", adc, dev_type1); | ||
369 | return -EINVAL; | ||
370 | }; | ||
371 | break; | ||
372 | default: | ||
373 | dev_err(info->dev, | ||
374 | "failed to identify the cable type: adc(0x%x)\n", adc); | ||
375 | return -EINVAL; | ||
376 | }; | ||
377 | |||
378 | return cable_type; | ||
379 | } | ||
380 | |||
381 | static int sm5502_muic_cable_handler(struct sm5502_muic_info *info, | ||
382 | bool attached) | ||
383 | { | ||
384 | static unsigned int prev_cable_type = SM5502_MUIC_ADC_GROUND; | ||
385 | const char **cable_names = info->edev->supported_cable; | ||
386 | unsigned int cable_type = SM5502_MUIC_ADC_GROUND; | ||
387 | unsigned int con_sw = DM_DP_SWITCH_OPEN; | ||
388 | unsigned int vbus_sw = VBUSIN_SWITCH_OPEN; | ||
389 | unsigned int idx = 0; | ||
390 | int ret; | ||
391 | |||
392 | if (!cable_names) | ||
393 | return 0; | ||
394 | |||
395 | /* Get the type of attached or detached cable */ | ||
396 | if (attached) | ||
397 | cable_type = sm5502_muic_get_cable_type(info); | ||
398 | else if (!attached) | ||
399 | cable_type = prev_cable_type; | ||
400 | prev_cable_type = cable_type; | ||
401 | |||
402 | switch (cable_type) { | ||
403 | case SM5502_MUIC_ADC_OPEN_USB: | ||
404 | idx = EXTCON_CABLE_USB; | ||
405 | con_sw = DM_DP_SWITCH_USB; | ||
406 | vbus_sw = VBUSIN_SWITCH_VBUSOUT_WITH_USB; | ||
407 | break; | ||
408 | case SM5502_MUIC_ADC_OPEN_TA: | ||
409 | idx = EXTCON_CABLE_TA; | ||
410 | con_sw = DM_DP_SWITCH_OPEN; | ||
411 | vbus_sw = VBUSIN_SWITCH_VBUSOUT; | ||
412 | break; | ||
413 | case SM5502_MUIC_ADC_OPEN_USB_OTG: | ||
414 | idx = EXTCON_CABLE_USB_HOST; | ||
415 | con_sw = DM_DP_SWITCH_USB; | ||
416 | vbus_sw = VBUSIN_SWITCH_OPEN; | ||
417 | break; | ||
418 | default: | ||
419 | dev_dbg(info->dev, | ||
420 | "cannot handle this cable_type (0x%x)\n", cable_type); | ||
421 | return 0; | ||
422 | }; | ||
423 | |||
424 | /* Change internal hardware path(DM_CON/DP_CON, VBUSIN) */ | ||
425 | ret = sm5502_muic_set_path(info, con_sw, vbus_sw, attached); | ||
426 | if (ret < 0) | ||
427 | return ret; | ||
428 | |||
429 | /* Change the state of external accessory */ | ||
430 | extcon_set_cable_state(info->edev, cable_names[idx], attached); | ||
431 | |||
432 | return 0; | ||
433 | } | ||
434 | |||
435 | static void sm5502_muic_irq_work(struct work_struct *work) | ||
436 | { | ||
437 | struct sm5502_muic_info *info = container_of(work, | ||
438 | struct sm5502_muic_info, irq_work); | ||
439 | int ret = 0; | ||
440 | |||
441 | if (!info->edev) | ||
442 | return; | ||
443 | |||
444 | mutex_lock(&info->mutex); | ||
445 | |||
446 | /* Detect attached or detached cables */ | ||
447 | if (info->irq_attach) { | ||
448 | ret = sm5502_muic_cable_handler(info, true); | ||
449 | info->irq_attach = false; | ||
450 | } | ||
451 | if (info->irq_detach) { | ||
452 | ret = sm5502_muic_cable_handler(info, false); | ||
453 | info->irq_detach = false; | ||
454 | } | ||
455 | |||
456 | if (ret < 0) | ||
457 | dev_err(info->dev, "failed to handle MUIC interrupt\n"); | ||
458 | |||
459 | mutex_unlock(&info->mutex); | ||
460 | |||
461 | return; | ||
462 | } | ||
463 | |||
464 | /* | ||
465 | * Sets irq_attach or irq_detach in sm5502_muic_info and returns 0. | ||
466 | * Returns -ESRCH if irq_type does not match registered IRQ for this dev type. | ||
467 | */ | ||
468 | static int sm5502_parse_irq(struct sm5502_muic_info *info, int irq_type) | ||
469 | { | ||
470 | switch (irq_type) { | ||
471 | case SM5502_IRQ_INT1_ATTACH: | ||
472 | info->irq_attach = true; | ||
473 | break; | ||
474 | case SM5502_IRQ_INT1_DETACH: | ||
475 | info->irq_detach = true; | ||
476 | break; | ||
477 | case SM5502_IRQ_INT1_KP: | ||
478 | case SM5502_IRQ_INT1_LKP: | ||
479 | case SM5502_IRQ_INT1_LKR: | ||
480 | case SM5502_IRQ_INT1_OVP_EVENT: | ||
481 | case SM5502_IRQ_INT1_OCP_EVENT: | ||
482 | case SM5502_IRQ_INT1_OVP_OCP_DIS: | ||
483 | case SM5502_IRQ_INT2_VBUS_DET: | ||
484 | case SM5502_IRQ_INT2_REV_ACCE: | ||
485 | case SM5502_IRQ_INT2_ADC_CHG: | ||
486 | case SM5502_IRQ_INT2_STUCK_KEY: | ||
487 | case SM5502_IRQ_INT2_STUCK_KEY_RCV: | ||
488 | case SM5502_IRQ_INT2_MHL: | ||
489 | default: | ||
490 | break; | ||
491 | } | ||
492 | |||
493 | return 0; | ||
494 | } | ||
495 | |||
496 | static irqreturn_t sm5502_muic_irq_handler(int irq, void *data) | ||
497 | { | ||
498 | struct sm5502_muic_info *info = data; | ||
499 | int i, irq_type = -1, ret; | ||
500 | |||
501 | for (i = 0; i < info->num_muic_irqs; i++) | ||
502 | if (irq == info->muic_irqs[i].virq) | ||
503 | irq_type = info->muic_irqs[i].irq; | ||
504 | |||
505 | ret = sm5502_parse_irq(info, irq_type); | ||
506 | if (ret < 0) { | ||
507 | dev_warn(info->dev, "cannot handle is interrupt:%d\n", | ||
508 | irq_type); | ||
509 | return IRQ_HANDLED; | ||
510 | } | ||
511 | schedule_work(&info->irq_work); | ||
512 | |||
513 | return IRQ_HANDLED; | ||
514 | } | ||
515 | |||
516 | static void sm5502_muic_detect_cable_wq(struct work_struct *work) | ||
517 | { | ||
518 | struct sm5502_muic_info *info = container_of(to_delayed_work(work), | ||
519 | struct sm5502_muic_info, wq_detcable); | ||
520 | int ret; | ||
521 | |||
522 | /* Notify the state of connector cable or not */ | ||
523 | ret = sm5502_muic_cable_handler(info, true); | ||
524 | if (ret < 0) | ||
525 | dev_warn(info->dev, "failed to detect cable state\n"); | ||
526 | } | ||
527 | |||
528 | static void sm5502_init_dev_type(struct sm5502_muic_info *info) | ||
529 | { | ||
530 | unsigned int reg_data, vendor_id, version_id; | ||
531 | int i, ret; | ||
532 | |||
533 | /* To test I2C, Print version_id and vendor_id of SM5502 */ | ||
534 | ret = regmap_read(info->regmap, SM5502_REG_DEVICE_ID, ®_data); | ||
535 | if (ret) { | ||
536 | dev_err(info->dev, | ||
537 | "failed to read DEVICE_ID register: %d\n", ret); | ||
538 | return; | ||
539 | } | ||
540 | |||
541 | vendor_id = ((reg_data & SM5502_REG_DEVICE_ID_VENDOR_MASK) >> | ||
542 | SM5502_REG_DEVICE_ID_VENDOR_SHIFT); | ||
543 | version_id = ((reg_data & SM5502_REG_DEVICE_ID_VERSION_MASK) >> | ||
544 | SM5502_REG_DEVICE_ID_VERSION_SHIFT); | ||
545 | |||
546 | dev_info(info->dev, "Device type: version: 0x%x, vendor: 0x%x\n", | ||
547 | version_id, vendor_id); | ||
548 | |||
549 | /* Initiazle the register of SM5502 device to bring-up */ | ||
550 | for (i = 0; i < info->num_reg_data; i++) { | ||
551 | unsigned int val = 0; | ||
552 | |||
553 | if (!info->reg_data[i].invert) | ||
554 | val |= ~info->reg_data[i].val; | ||
555 | else | ||
556 | val = info->reg_data[i].val; | ||
557 | regmap_write(info->regmap, info->reg_data[i].reg, val); | ||
558 | } | ||
559 | } | ||
560 | |||
561 | static int sm5022_muic_i2c_probe(struct i2c_client *i2c, | ||
562 | const struct i2c_device_id *id) | ||
563 | { | ||
564 | struct device_node *np = i2c->dev.of_node; | ||
565 | struct sm5502_muic_info *info; | ||
566 | int i, ret, irq_flags; | ||
567 | |||
568 | if (!np) | ||
569 | return -EINVAL; | ||
570 | |||
571 | info = devm_kzalloc(&i2c->dev, sizeof(*info), GFP_KERNEL); | ||
572 | if (!info) | ||
573 | return -ENOMEM; | ||
574 | i2c_set_clientdata(i2c, info); | ||
575 | |||
576 | info->dev = &i2c->dev; | ||
577 | info->i2c = i2c; | ||
578 | info->irq = i2c->irq; | ||
579 | info->muic_irqs = sm5502_muic_irqs; | ||
580 | info->num_muic_irqs = ARRAY_SIZE(sm5502_muic_irqs); | ||
581 | info->reg_data = sm5502_reg_data; | ||
582 | info->num_reg_data = ARRAY_SIZE(sm5502_reg_data); | ||
583 | |||
584 | mutex_init(&info->mutex); | ||
585 | |||
586 | INIT_WORK(&info->irq_work, sm5502_muic_irq_work); | ||
587 | |||
588 | info->regmap = devm_regmap_init_i2c(i2c, &sm5502_muic_regmap_config); | ||
589 | if (IS_ERR(info->regmap)) { | ||
590 | ret = PTR_ERR(info->regmap); | ||
591 | dev_err(info->dev, "failed to allocate register map: %d\n", | ||
592 | ret); | ||
593 | return ret; | ||
594 | } | ||
595 | |||
596 | /* Support irq domain for SM5502 MUIC device */ | ||
597 | irq_flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT | IRQF_SHARED; | ||
598 | ret = regmap_add_irq_chip(info->regmap, info->irq, irq_flags, 0, | ||
599 | &sm5502_muic_irq_chip, &info->irq_data); | ||
600 | if (ret != 0) { | ||
601 | dev_err(info->dev, "failed to request IRQ %d: %d\n", | ||
602 | info->irq, ret); | ||
603 | return ret; | ||
604 | } | ||
605 | |||
606 | for (i = 0; i < info->num_muic_irqs; i++) { | ||
607 | struct muic_irq *muic_irq = &info->muic_irqs[i]; | ||
608 | unsigned int virq = 0; | ||
609 | |||
610 | virq = regmap_irq_get_virq(info->irq_data, muic_irq->irq); | ||
611 | if (virq <= 0) | ||
612 | return -EINVAL; | ||
613 | muic_irq->virq = virq; | ||
614 | |||
615 | ret = devm_request_threaded_irq(info->dev, virq, NULL, | ||
616 | sm5502_muic_irq_handler, | ||
617 | IRQF_NO_SUSPEND, | ||
618 | muic_irq->name, info); | ||
619 | if (ret) { | ||
620 | dev_err(info->dev, "failed: irq request (IRQ: %d," | ||
621 | " error :%d)\n", muic_irq->irq, ret); | ||
622 | return ret; | ||
623 | } | ||
624 | } | ||
625 | |||
626 | /* Allocate extcon device */ | ||
627 | info->edev = devm_extcon_dev_allocate(info->dev, sm5502_extcon_cable); | ||
628 | if (IS_ERR(info->edev)) { | ||
629 | dev_err(info->dev, "failed to allocate memory for extcon\n"); | ||
630 | return -ENOMEM; | ||
631 | } | ||
632 | info->edev->name = np->name; | ||
633 | |||
634 | /* Register extcon device */ | ||
635 | ret = devm_extcon_dev_register(info->dev, info->edev); | ||
636 | if (ret) { | ||
637 | dev_err(info->dev, "failed to register extcon device\n"); | ||
638 | return ret; | ||
639 | } | ||
640 | |||
641 | /* | ||
642 | * Detect accessory after completing the initialization of platform | ||
643 | * | ||
644 | * - Use delayed workqueue to detect cable state and then | ||
645 | * notify cable state to notifiee/platform through uevent. | ||
646 | * After completing the booting of platform, the extcon provider | ||
647 | * driver should notify cable state to upper layer. | ||
648 | */ | ||
649 | INIT_DELAYED_WORK(&info->wq_detcable, sm5502_muic_detect_cable_wq); | ||
650 | queue_delayed_work(system_power_efficient_wq, &info->wq_detcable, | ||
651 | msecs_to_jiffies(DELAY_MS_DEFAULT)); | ||
652 | |||
653 | /* Initialize SM5502 device and print vendor id and version id */ | ||
654 | sm5502_init_dev_type(info); | ||
655 | |||
656 | return 0; | ||
657 | } | ||
658 | |||
659 | static int sm5502_muic_i2c_remove(struct i2c_client *i2c) | ||
660 | { | ||
661 | struct sm5502_muic_info *info = i2c_get_clientdata(i2c); | ||
662 | |||
663 | regmap_del_irq_chip(info->irq, info->irq_data); | ||
664 | |||
665 | return 0; | ||
666 | } | ||
667 | |||
668 | static struct of_device_id sm5502_dt_match[] = { | ||
669 | { .compatible = "siliconmitus,sm5502-muic" }, | ||
670 | { }, | ||
671 | }; | ||
672 | |||
673 | #ifdef CONFIG_PM_SLEEP | ||
674 | static int sm5502_muic_suspend(struct device *dev) | ||
675 | { | ||
676 | struct i2c_client *i2c = container_of(dev, struct i2c_client, dev); | ||
677 | struct sm5502_muic_info *info = i2c_get_clientdata(i2c); | ||
678 | |||
679 | enable_irq_wake(info->irq); | ||
680 | |||
681 | return 0; | ||
682 | } | ||
683 | |||
684 | static int sm5502_muic_resume(struct device *dev) | ||
685 | { | ||
686 | struct i2c_client *i2c = container_of(dev, struct i2c_client, dev); | ||
687 | struct sm5502_muic_info *info = i2c_get_clientdata(i2c); | ||
688 | |||
689 | disable_irq_wake(info->irq); | ||
690 | |||
691 | return 0; | ||
692 | } | ||
693 | #endif | ||
694 | |||
695 | static SIMPLE_DEV_PM_OPS(sm5502_muic_pm_ops, | ||
696 | sm5502_muic_suspend, sm5502_muic_resume); | ||
697 | |||
698 | static const struct i2c_device_id sm5502_i2c_id[] = { | ||
699 | { "sm5502", TYPE_SM5502 }, | ||
700 | { } | ||
701 | }; | ||
702 | MODULE_DEVICE_TABLE(i2c, sm5502_i2c_id); | ||
703 | |||
704 | static struct i2c_driver sm5502_muic_i2c_driver = { | ||
705 | .driver = { | ||
706 | .name = "sm5502", | ||
707 | .owner = THIS_MODULE, | ||
708 | .pm = &sm5502_muic_pm_ops, | ||
709 | .of_match_table = sm5502_dt_match, | ||
710 | }, | ||
711 | .probe = sm5022_muic_i2c_probe, | ||
712 | .remove = sm5502_muic_i2c_remove, | ||
713 | .id_table = sm5502_i2c_id, | ||
714 | }; | ||
715 | |||
716 | static int __init sm5502_muic_i2c_init(void) | ||
717 | { | ||
718 | return i2c_add_driver(&sm5502_muic_i2c_driver); | ||
719 | } | ||
720 | subsys_initcall(sm5502_muic_i2c_init); | ||
721 | |||
722 | MODULE_DESCRIPTION("Silicon Mitus SM5502 Extcon driver"); | ||
723 | MODULE_AUTHOR("Chanwoo Choi <cw00.choi@samsung.com>"); | ||
724 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 6cc4b6acc22a..fb824f501197 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig | |||
@@ -384,6 +384,7 @@ config MFD_MAX77693 | |||
384 | depends on I2C=y | 384 | depends on I2C=y |
385 | select MFD_CORE | 385 | select MFD_CORE |
386 | select REGMAP_I2C | 386 | select REGMAP_I2C |
387 | select REGMAP_IRQ | ||
387 | help | 388 | help |
388 | Say yes here to add support for Maxim Semiconductor MAX77693. | 389 | Say yes here to add support for Maxim Semiconductor MAX77693. |
389 | This is a companion Power Management IC with Flash, Haptic, Charger, | 390 | This is a companion Power Management IC with Flash, Haptic, Charger, |
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index 8afedba535c7..8c6e7bba4660 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile | |||
@@ -116,7 +116,7 @@ obj-$(CONFIG_MFD_DA9063) += da9063.o | |||
116 | 116 | ||
117 | obj-$(CONFIG_MFD_MAX14577) += max14577.o | 117 | obj-$(CONFIG_MFD_MAX14577) += max14577.o |
118 | obj-$(CONFIG_MFD_MAX77686) += max77686.o max77686-irq.o | 118 | obj-$(CONFIG_MFD_MAX77686) += max77686.o max77686-irq.o |
119 | obj-$(CONFIG_MFD_MAX77693) += max77693.o max77693-irq.o | 119 | obj-$(CONFIG_MFD_MAX77693) += max77693.o |
120 | obj-$(CONFIG_MFD_MAX8907) += max8907.o | 120 | obj-$(CONFIG_MFD_MAX8907) += max8907.o |
121 | max8925-objs := max8925-core.o max8925-i2c.o | 121 | max8925-objs := max8925-core.o max8925-i2c.o |
122 | obj-$(CONFIG_MFD_MAX8925) += max8925.o | 122 | obj-$(CONFIG_MFD_MAX8925) += max8925.o |
diff --git a/drivers/mfd/max77693-irq.c b/drivers/mfd/max77693-irq.c deleted file mode 100644 index 66b58fe77094..000000000000 --- a/drivers/mfd/max77693-irq.c +++ /dev/null | |||
@@ -1,336 +0,0 @@ | |||
1 | /* | ||
2 | * max77693-irq.c - Interrupt controller support for MAX77693 | ||
3 | * | ||
4 | * Copyright (C) 2012 Samsung Electronics Co.Ltd | ||
5 | * SangYoung Son <hello.son@samsung.com> | ||
6 | * | ||
7 | * This program is not provided / owned by Maxim Integrated Products. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
22 | * | ||
23 | * This driver is based on max8997-irq.c | ||
24 | */ | ||
25 | |||
26 | #include <linux/err.h> | ||
27 | #include <linux/irq.h> | ||
28 | #include <linux/interrupt.h> | ||
29 | #include <linux/module.h> | ||
30 | #include <linux/irqdomain.h> | ||
31 | #include <linux/mfd/max77693.h> | ||
32 | #include <linux/mfd/max77693-private.h> | ||
33 | |||
34 | static const u8 max77693_mask_reg[] = { | ||
35 | [LED_INT] = MAX77693_LED_REG_FLASH_INT_MASK, | ||
36 | [TOPSYS_INT] = MAX77693_PMIC_REG_TOPSYS_INT_MASK, | ||
37 | [CHG_INT] = MAX77693_CHG_REG_CHG_INT_MASK, | ||
38 | [MUIC_INT1] = MAX77693_MUIC_REG_INTMASK1, | ||
39 | [MUIC_INT2] = MAX77693_MUIC_REG_INTMASK2, | ||
40 | [MUIC_INT3] = MAX77693_MUIC_REG_INTMASK3, | ||
41 | }; | ||
42 | |||
43 | static struct regmap *max77693_get_regmap(struct max77693_dev *max77693, | ||
44 | enum max77693_irq_source src) | ||
45 | { | ||
46 | switch (src) { | ||
47 | case LED_INT ... CHG_INT: | ||
48 | return max77693->regmap; | ||
49 | case MUIC_INT1 ... MUIC_INT3: | ||
50 | return max77693->regmap_muic; | ||
51 | default: | ||
52 | return ERR_PTR(-EINVAL); | ||
53 | } | ||
54 | } | ||
55 | |||
56 | struct max77693_irq_data { | ||
57 | int mask; | ||
58 | enum max77693_irq_source group; | ||
59 | }; | ||
60 | |||
61 | #define DECLARE_IRQ(idx, _group, _mask) \ | ||
62 | [(idx)] = { .group = (_group), .mask = (_mask) } | ||
63 | static const struct max77693_irq_data max77693_irqs[] = { | ||
64 | DECLARE_IRQ(MAX77693_LED_IRQ_FLED2_OPEN, LED_INT, 1 << 0), | ||
65 | DECLARE_IRQ(MAX77693_LED_IRQ_FLED2_SHORT, LED_INT, 1 << 1), | ||
66 | DECLARE_IRQ(MAX77693_LED_IRQ_FLED1_OPEN, LED_INT, 1 << 2), | ||
67 | DECLARE_IRQ(MAX77693_LED_IRQ_FLED1_SHORT, LED_INT, 1 << 3), | ||
68 | DECLARE_IRQ(MAX77693_LED_IRQ_MAX_FLASH, LED_INT, 1 << 4), | ||
69 | |||
70 | DECLARE_IRQ(MAX77693_TOPSYS_IRQ_T120C_INT, TOPSYS_INT, 1 << 0), | ||
71 | DECLARE_IRQ(MAX77693_TOPSYS_IRQ_T140C_INT, TOPSYS_INT, 1 << 1), | ||
72 | DECLARE_IRQ(MAX77693_TOPSYS_IRQ_LOWSYS_INT, TOPSYS_INT, 1 << 3), | ||
73 | |||
74 | DECLARE_IRQ(MAX77693_CHG_IRQ_BYP_I, CHG_INT, 1 << 0), | ||
75 | DECLARE_IRQ(MAX77693_CHG_IRQ_THM_I, CHG_INT, 1 << 2), | ||
76 | DECLARE_IRQ(MAX77693_CHG_IRQ_BAT_I, CHG_INT, 1 << 3), | ||
77 | DECLARE_IRQ(MAX77693_CHG_IRQ_CHG_I, CHG_INT, 1 << 4), | ||
78 | DECLARE_IRQ(MAX77693_CHG_IRQ_CHGIN_I, CHG_INT, 1 << 6), | ||
79 | |||
80 | DECLARE_IRQ(MAX77693_MUIC_IRQ_INT1_ADC, MUIC_INT1, 1 << 0), | ||
81 | DECLARE_IRQ(MAX77693_MUIC_IRQ_INT1_ADC_LOW, MUIC_INT1, 1 << 1), | ||
82 | DECLARE_IRQ(MAX77693_MUIC_IRQ_INT1_ADC_ERR, MUIC_INT1, 1 << 2), | ||
83 | DECLARE_IRQ(MAX77693_MUIC_IRQ_INT1_ADC1K, MUIC_INT1, 1 << 3), | ||
84 | |||
85 | DECLARE_IRQ(MAX77693_MUIC_IRQ_INT2_CHGTYP, MUIC_INT2, 1 << 0), | ||
86 | DECLARE_IRQ(MAX77693_MUIC_IRQ_INT2_CHGDETREUN, MUIC_INT2, 1 << 1), | ||
87 | DECLARE_IRQ(MAX77693_MUIC_IRQ_INT2_DCDTMR, MUIC_INT2, 1 << 2), | ||
88 | DECLARE_IRQ(MAX77693_MUIC_IRQ_INT2_DXOVP, MUIC_INT2, 1 << 3), | ||
89 | DECLARE_IRQ(MAX77693_MUIC_IRQ_INT2_VBVOLT, MUIC_INT2, 1 << 4), | ||
90 | DECLARE_IRQ(MAX77693_MUIC_IRQ_INT2_VIDRM, MUIC_INT2, 1 << 5), | ||
91 | |||
92 | DECLARE_IRQ(MAX77693_MUIC_IRQ_INT3_EOC, MUIC_INT3, 1 << 0), | ||
93 | DECLARE_IRQ(MAX77693_MUIC_IRQ_INT3_CGMBC, MUIC_INT3, 1 << 1), | ||
94 | DECLARE_IRQ(MAX77693_MUIC_IRQ_INT3_OVP, MUIC_INT3, 1 << 2), | ||
95 | DECLARE_IRQ(MAX77693_MUIC_IRQ_INT3_MBCCHG_ERR, MUIC_INT3, 1 << 3), | ||
96 | DECLARE_IRQ(MAX77693_MUIC_IRQ_INT3_CHG_ENABLED, MUIC_INT3, 1 << 4), | ||
97 | DECLARE_IRQ(MAX77693_MUIC_IRQ_INT3_BAT_DET, MUIC_INT3, 1 << 5), | ||
98 | }; | ||
99 | |||
100 | static void max77693_irq_lock(struct irq_data *data) | ||
101 | { | ||
102 | struct max77693_dev *max77693 = irq_get_chip_data(data->irq); | ||
103 | |||
104 | mutex_lock(&max77693->irqlock); | ||
105 | } | ||
106 | |||
107 | static void max77693_irq_sync_unlock(struct irq_data *data) | ||
108 | { | ||
109 | struct max77693_dev *max77693 = irq_get_chip_data(data->irq); | ||
110 | int i; | ||
111 | |||
112 | for (i = 0; i < MAX77693_IRQ_GROUP_NR; i++) { | ||
113 | u8 mask_reg = max77693_mask_reg[i]; | ||
114 | struct regmap *map = max77693_get_regmap(max77693, i); | ||
115 | |||
116 | if (mask_reg == MAX77693_REG_INVALID || | ||
117 | IS_ERR_OR_NULL(map)) | ||
118 | continue; | ||
119 | max77693->irq_masks_cache[i] = max77693->irq_masks_cur[i]; | ||
120 | |||
121 | max77693_write_reg(map, max77693_mask_reg[i], | ||
122 | max77693->irq_masks_cur[i]); | ||
123 | } | ||
124 | |||
125 | mutex_unlock(&max77693->irqlock); | ||
126 | } | ||
127 | |||
128 | static const inline struct max77693_irq_data * | ||
129 | irq_to_max77693_irq(struct max77693_dev *max77693, int irq) | ||
130 | { | ||
131 | struct irq_data *data = irq_get_irq_data(irq); | ||
132 | return &max77693_irqs[data->hwirq]; | ||
133 | } | ||
134 | |||
135 | static void max77693_irq_mask(struct irq_data *data) | ||
136 | { | ||
137 | struct max77693_dev *max77693 = irq_get_chip_data(data->irq); | ||
138 | const struct max77693_irq_data *irq_data = | ||
139 | irq_to_max77693_irq(max77693, data->irq); | ||
140 | |||
141 | if (irq_data->group >= MAX77693_IRQ_GROUP_NR) | ||
142 | return; | ||
143 | |||
144 | if (irq_data->group >= MUIC_INT1 && irq_data->group <= MUIC_INT3) | ||
145 | max77693->irq_masks_cur[irq_data->group] &= ~irq_data->mask; | ||
146 | else | ||
147 | max77693->irq_masks_cur[irq_data->group] |= irq_data->mask; | ||
148 | } | ||
149 | |||
150 | static void max77693_irq_unmask(struct irq_data *data) | ||
151 | { | ||
152 | struct max77693_dev *max77693 = irq_get_chip_data(data->irq); | ||
153 | const struct max77693_irq_data *irq_data = | ||
154 | irq_to_max77693_irq(max77693, data->irq); | ||
155 | |||
156 | if (irq_data->group >= MAX77693_IRQ_GROUP_NR) | ||
157 | return; | ||
158 | |||
159 | if (irq_data->group >= MUIC_INT1 && irq_data->group <= MUIC_INT3) | ||
160 | max77693->irq_masks_cur[irq_data->group] |= irq_data->mask; | ||
161 | else | ||
162 | max77693->irq_masks_cur[irq_data->group] &= ~irq_data->mask; | ||
163 | } | ||
164 | |||
165 | static struct irq_chip max77693_irq_chip = { | ||
166 | .name = "max77693", | ||
167 | .irq_bus_lock = max77693_irq_lock, | ||
168 | .irq_bus_sync_unlock = max77693_irq_sync_unlock, | ||
169 | .irq_mask = max77693_irq_mask, | ||
170 | .irq_unmask = max77693_irq_unmask, | ||
171 | }; | ||
172 | |||
173 | #define MAX77693_IRQSRC_CHG (1 << 0) | ||
174 | #define MAX77693_IRQSRC_TOP (1 << 1) | ||
175 | #define MAX77693_IRQSRC_FLASH (1 << 2) | ||
176 | #define MAX77693_IRQSRC_MUIC (1 << 3) | ||
177 | static irqreturn_t max77693_irq_thread(int irq, void *data) | ||
178 | { | ||
179 | struct max77693_dev *max77693 = data; | ||
180 | u8 irq_reg[MAX77693_IRQ_GROUP_NR] = {}; | ||
181 | u8 irq_src; | ||
182 | int ret; | ||
183 | int i, cur_irq; | ||
184 | |||
185 | ret = max77693_read_reg(max77693->regmap, MAX77693_PMIC_REG_INTSRC, | ||
186 | &irq_src); | ||
187 | if (ret < 0) { | ||
188 | dev_err(max77693->dev, "Failed to read interrupt source: %d\n", | ||
189 | ret); | ||
190 | return IRQ_NONE; | ||
191 | } | ||
192 | |||
193 | if (irq_src & MAX77693_IRQSRC_CHG) | ||
194 | /* CHG_INT */ | ||
195 | ret = max77693_read_reg(max77693->regmap, MAX77693_CHG_REG_CHG_INT, | ||
196 | &irq_reg[CHG_INT]); | ||
197 | |||
198 | if (irq_src & MAX77693_IRQSRC_TOP) | ||
199 | /* TOPSYS_INT */ | ||
200 | ret = max77693_read_reg(max77693->regmap, | ||
201 | MAX77693_PMIC_REG_TOPSYS_INT, &irq_reg[TOPSYS_INT]); | ||
202 | |||
203 | if (irq_src & MAX77693_IRQSRC_FLASH) | ||
204 | /* LED_INT */ | ||
205 | ret = max77693_read_reg(max77693->regmap, | ||
206 | MAX77693_LED_REG_FLASH_INT, &irq_reg[LED_INT]); | ||
207 | |||
208 | if (irq_src & MAX77693_IRQSRC_MUIC) | ||
209 | /* MUIC INT1 ~ INT3 */ | ||
210 | max77693_bulk_read(max77693->regmap_muic, MAX77693_MUIC_REG_INT1, | ||
211 | MAX77693_NUM_IRQ_MUIC_REGS, &irq_reg[MUIC_INT1]); | ||
212 | |||
213 | /* Apply masking */ | ||
214 | for (i = 0; i < MAX77693_IRQ_GROUP_NR; i++) { | ||
215 | if (i >= MUIC_INT1 && i <= MUIC_INT3) | ||
216 | irq_reg[i] &= max77693->irq_masks_cur[i]; | ||
217 | else | ||
218 | irq_reg[i] &= ~max77693->irq_masks_cur[i]; | ||
219 | } | ||
220 | |||
221 | /* Report */ | ||
222 | for (i = 0; i < MAX77693_IRQ_NR; i++) { | ||
223 | if (irq_reg[max77693_irqs[i].group] & max77693_irqs[i].mask) { | ||
224 | cur_irq = irq_find_mapping(max77693->irq_domain, i); | ||
225 | if (cur_irq) | ||
226 | handle_nested_irq(cur_irq); | ||
227 | } | ||
228 | } | ||
229 | |||
230 | return IRQ_HANDLED; | ||
231 | } | ||
232 | |||
233 | int max77693_irq_resume(struct max77693_dev *max77693) | ||
234 | { | ||
235 | if (max77693->irq) | ||
236 | max77693_irq_thread(0, max77693); | ||
237 | |||
238 | return 0; | ||
239 | } | ||
240 | |||
241 | static int max77693_irq_domain_map(struct irq_domain *d, unsigned int irq, | ||
242 | irq_hw_number_t hw) | ||
243 | { | ||
244 | struct max77693_dev *max77693 = d->host_data; | ||
245 | |||
246 | irq_set_chip_data(irq, max77693); | ||
247 | irq_set_chip_and_handler(irq, &max77693_irq_chip, handle_edge_irq); | ||
248 | irq_set_nested_thread(irq, 1); | ||
249 | #ifdef CONFIG_ARM | ||
250 | set_irq_flags(irq, IRQF_VALID); | ||
251 | #else | ||
252 | irq_set_noprobe(irq); | ||
253 | #endif | ||
254 | return 0; | ||
255 | } | ||
256 | |||
257 | static struct irq_domain_ops max77693_irq_domain_ops = { | ||
258 | .map = max77693_irq_domain_map, | ||
259 | }; | ||
260 | |||
261 | int max77693_irq_init(struct max77693_dev *max77693) | ||
262 | { | ||
263 | struct irq_domain *domain; | ||
264 | int i; | ||
265 | int ret = 0; | ||
266 | u8 intsrc_mask; | ||
267 | |||
268 | mutex_init(&max77693->irqlock); | ||
269 | |||
270 | /* Mask individual interrupt sources */ | ||
271 | for (i = 0; i < MAX77693_IRQ_GROUP_NR; i++) { | ||
272 | struct regmap *map; | ||
273 | /* MUIC IRQ 0:MASK 1:NOT MASK */ | ||
274 | /* Other IRQ 1:MASK 0:NOT MASK */ | ||
275 | if (i >= MUIC_INT1 && i <= MUIC_INT3) { | ||
276 | max77693->irq_masks_cur[i] = 0x00; | ||
277 | max77693->irq_masks_cache[i] = 0x00; | ||
278 | } else { | ||
279 | max77693->irq_masks_cur[i] = 0xff; | ||
280 | max77693->irq_masks_cache[i] = 0xff; | ||
281 | } | ||
282 | map = max77693_get_regmap(max77693, i); | ||
283 | |||
284 | if (IS_ERR_OR_NULL(map)) | ||
285 | continue; | ||
286 | if (max77693_mask_reg[i] == MAX77693_REG_INVALID) | ||
287 | continue; | ||
288 | if (i >= MUIC_INT1 && i <= MUIC_INT3) | ||
289 | max77693_write_reg(map, max77693_mask_reg[i], 0x00); | ||
290 | else | ||
291 | max77693_write_reg(map, max77693_mask_reg[i], 0xff); | ||
292 | } | ||
293 | |||
294 | domain = irq_domain_add_linear(NULL, MAX77693_IRQ_NR, | ||
295 | &max77693_irq_domain_ops, max77693); | ||
296 | if (!domain) { | ||
297 | dev_err(max77693->dev, "could not create irq domain\n"); | ||
298 | ret = -ENODEV; | ||
299 | goto err_irq; | ||
300 | } | ||
301 | max77693->irq_domain = domain; | ||
302 | |||
303 | /* Unmask max77693 interrupt */ | ||
304 | ret = max77693_read_reg(max77693->regmap, | ||
305 | MAX77693_PMIC_REG_INTSRC_MASK, &intsrc_mask); | ||
306 | if (ret < 0) { | ||
307 | dev_err(max77693->dev, "fail to read PMIC register\n"); | ||
308 | goto err_irq; | ||
309 | } | ||
310 | |||
311 | intsrc_mask &= ~(MAX77693_IRQSRC_CHG); | ||
312 | intsrc_mask &= ~(MAX77693_IRQSRC_FLASH); | ||
313 | intsrc_mask &= ~(MAX77693_IRQSRC_MUIC); | ||
314 | ret = max77693_write_reg(max77693->regmap, | ||
315 | MAX77693_PMIC_REG_INTSRC_MASK, intsrc_mask); | ||
316 | if (ret < 0) { | ||
317 | dev_err(max77693->dev, "fail to write PMIC register\n"); | ||
318 | goto err_irq; | ||
319 | } | ||
320 | |||
321 | ret = request_threaded_irq(max77693->irq, NULL, max77693_irq_thread, | ||
322 | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, | ||
323 | "max77693-irq", max77693); | ||
324 | if (ret) | ||
325 | dev_err(max77693->dev, "Failed to request IRQ %d: %d\n", | ||
326 | max77693->irq, ret); | ||
327 | |||
328 | err_irq: | ||
329 | return ret; | ||
330 | } | ||
331 | |||
332 | void max77693_irq_exit(struct max77693_dev *max77693) | ||
333 | { | ||
334 | if (max77693->irq) | ||
335 | free_irq(max77693->irq, max77693); | ||
336 | } | ||
diff --git a/drivers/mfd/max77693.c b/drivers/mfd/max77693.c index 7e05428c756d..249c139ef04a 100644 --- a/drivers/mfd/max77693.c +++ b/drivers/mfd/max77693.c | |||
@@ -49,62 +49,62 @@ static const struct mfd_cell max77693_devs[] = { | |||
49 | { .name = "max77693-haptic", }, | 49 | { .name = "max77693-haptic", }, |
50 | }; | 50 | }; |
51 | 51 | ||
52 | int max77693_read_reg(struct regmap *map, u8 reg, u8 *dest) | 52 | static const struct regmap_config max77693_regmap_config = { |
53 | { | 53 | .reg_bits = 8, |
54 | unsigned int val; | 54 | .val_bits = 8, |
55 | int ret; | 55 | .max_register = MAX77693_PMIC_REG_END, |
56 | 56 | }; | |
57 | ret = regmap_read(map, reg, &val); | ||
58 | *dest = val; | ||
59 | |||
60 | return ret; | ||
61 | } | ||
62 | EXPORT_SYMBOL_GPL(max77693_read_reg); | ||
63 | |||
64 | int max77693_bulk_read(struct regmap *map, u8 reg, int count, u8 *buf) | ||
65 | { | ||
66 | int ret; | ||
67 | |||
68 | ret = regmap_bulk_read(map, reg, buf, count); | ||
69 | |||
70 | return ret; | ||
71 | } | ||
72 | EXPORT_SYMBOL_GPL(max77693_bulk_read); | ||
73 | |||
74 | int max77693_write_reg(struct regmap *map, u8 reg, u8 value) | ||
75 | { | ||
76 | int ret; | ||
77 | |||
78 | ret = regmap_write(map, reg, value); | ||
79 | |||
80 | return ret; | ||
81 | } | ||
82 | EXPORT_SYMBOL_GPL(max77693_write_reg); | ||
83 | |||
84 | int max77693_bulk_write(struct regmap *map, u8 reg, int count, u8 *buf) | ||
85 | { | ||
86 | int ret; | ||
87 | 57 | ||
88 | ret = regmap_bulk_write(map, reg, buf, count); | 58 | static const struct regmap_irq max77693_led_irqs[] = { |
59 | { .mask = LED_IRQ_FLED2_OPEN, }, | ||
60 | { .mask = LED_IRQ_FLED2_SHORT, }, | ||
61 | { .mask = LED_IRQ_FLED1_OPEN, }, | ||
62 | { .mask = LED_IRQ_FLED1_SHORT, }, | ||
63 | { .mask = LED_IRQ_MAX_FLASH, }, | ||
64 | }; | ||
89 | 65 | ||
90 | return ret; | 66 | static const struct regmap_irq_chip max77693_led_irq_chip = { |
91 | } | 67 | .name = "max77693-led", |
92 | EXPORT_SYMBOL_GPL(max77693_bulk_write); | 68 | .status_base = MAX77693_LED_REG_FLASH_INT, |
69 | .mask_base = MAX77693_LED_REG_FLASH_INT_MASK, | ||
70 | .mask_invert = false, | ||
71 | .num_regs = 1, | ||
72 | .irqs = max77693_led_irqs, | ||
73 | .num_irqs = ARRAY_SIZE(max77693_led_irqs), | ||
74 | }; | ||
93 | 75 | ||
94 | int max77693_update_reg(struct regmap *map, u8 reg, u8 val, u8 mask) | 76 | static const struct regmap_irq max77693_topsys_irqs[] = { |
95 | { | 77 | { .mask = TOPSYS_IRQ_T120C_INT, }, |
96 | int ret; | 78 | { .mask = TOPSYS_IRQ_T140C_INT, }, |
79 | { .mask = TOPSYS_IRQ_LOWSYS_INT, }, | ||
80 | }; | ||
97 | 81 | ||
98 | ret = regmap_update_bits(map, reg, mask, val); | 82 | static const struct regmap_irq_chip max77693_topsys_irq_chip = { |
83 | .name = "max77693-topsys", | ||
84 | .status_base = MAX77693_PMIC_REG_TOPSYS_INT, | ||
85 | .mask_base = MAX77693_PMIC_REG_TOPSYS_INT_MASK, | ||
86 | .mask_invert = false, | ||
87 | .num_regs = 1, | ||
88 | .irqs = max77693_topsys_irqs, | ||
89 | .num_irqs = ARRAY_SIZE(max77693_topsys_irqs), | ||
90 | }; | ||
99 | 91 | ||
100 | return ret; | 92 | static const struct regmap_irq max77693_charger_irqs[] = { |
101 | } | 93 | { .mask = CHG_IRQ_BYP_I, }, |
102 | EXPORT_SYMBOL_GPL(max77693_update_reg); | 94 | { .mask = CHG_IRQ_THM_I, }, |
95 | { .mask = CHG_IRQ_BAT_I, }, | ||
96 | { .mask = CHG_IRQ_CHG_I, }, | ||
97 | { .mask = CHG_IRQ_CHGIN_I, }, | ||
98 | }; | ||
103 | 99 | ||
104 | static const struct regmap_config max77693_regmap_config = { | 100 | static const struct regmap_irq_chip max77693_charger_irq_chip = { |
105 | .reg_bits = 8, | 101 | .name = "max77693-charger", |
106 | .val_bits = 8, | 102 | .status_base = MAX77693_CHG_REG_CHG_INT, |
107 | .max_register = MAX77693_PMIC_REG_END, | 103 | .mask_base = MAX77693_CHG_REG_CHG_INT_MASK, |
104 | .mask_invert = false, | ||
105 | .num_regs = 1, | ||
106 | .irqs = max77693_charger_irqs, | ||
107 | .num_irqs = ARRAY_SIZE(max77693_charger_irqs), | ||
108 | }; | 108 | }; |
109 | 109 | ||
110 | static const struct regmap_config max77693_regmap_muic_config = { | 110 | static const struct regmap_config max77693_regmap_muic_config = { |
@@ -113,11 +113,42 @@ static const struct regmap_config max77693_regmap_muic_config = { | |||
113 | .max_register = MAX77693_MUIC_REG_END, | 113 | .max_register = MAX77693_MUIC_REG_END, |
114 | }; | 114 | }; |
115 | 115 | ||
116 | static const struct regmap_irq max77693_muic_irqs[] = { | ||
117 | { .reg_offset = 0, .mask = MUIC_IRQ_INT1_ADC, }, | ||
118 | { .reg_offset = 0, .mask = MUIC_IRQ_INT1_ADC_LOW, }, | ||
119 | { .reg_offset = 0, .mask = MUIC_IRQ_INT1_ADC_ERR, }, | ||
120 | { .reg_offset = 0, .mask = MUIC_IRQ_INT1_ADC1K, }, | ||
121 | |||
122 | { .reg_offset = 1, .mask = MUIC_IRQ_INT2_CHGTYP, }, | ||
123 | { .reg_offset = 1, .mask = MUIC_IRQ_INT2_CHGDETREUN, }, | ||
124 | { .reg_offset = 1, .mask = MUIC_IRQ_INT2_DCDTMR, }, | ||
125 | { .reg_offset = 1, .mask = MUIC_IRQ_INT2_DXOVP, }, | ||
126 | { .reg_offset = 1, .mask = MUIC_IRQ_INT2_VBVOLT, }, | ||
127 | { .reg_offset = 1, .mask = MUIC_IRQ_INT2_VIDRM, }, | ||
128 | |||
129 | { .reg_offset = 2, .mask = MUIC_IRQ_INT3_EOC, }, | ||
130 | { .reg_offset = 2, .mask = MUIC_IRQ_INT3_CGMBC, }, | ||
131 | { .reg_offset = 2, .mask = MUIC_IRQ_INT3_OVP, }, | ||
132 | { .reg_offset = 2, .mask = MUIC_IRQ_INT3_MBCCHG_ERR, }, | ||
133 | { .reg_offset = 2, .mask = MUIC_IRQ_INT3_CHG_ENABLED, }, | ||
134 | { .reg_offset = 2, .mask = MUIC_IRQ_INT3_BAT_DET, }, | ||
135 | }; | ||
136 | |||
137 | static const struct regmap_irq_chip max77693_muic_irq_chip = { | ||
138 | .name = "max77693-muic", | ||
139 | .status_base = MAX77693_MUIC_REG_INT1, | ||
140 | .mask_base = MAX77693_MUIC_REG_INTMASK1, | ||
141 | .mask_invert = true, | ||
142 | .num_regs = 3, | ||
143 | .irqs = max77693_muic_irqs, | ||
144 | .num_irqs = ARRAY_SIZE(max77693_muic_irqs), | ||
145 | }; | ||
146 | |||
116 | static int max77693_i2c_probe(struct i2c_client *i2c, | 147 | static int max77693_i2c_probe(struct i2c_client *i2c, |
117 | const struct i2c_device_id *id) | 148 | const struct i2c_device_id *id) |
118 | { | 149 | { |
119 | struct max77693_dev *max77693; | 150 | struct max77693_dev *max77693; |
120 | u8 reg_data; | 151 | unsigned int reg_data; |
121 | int ret = 0; | 152 | int ret = 0; |
122 | 153 | ||
123 | max77693 = devm_kzalloc(&i2c->dev, | 154 | max77693 = devm_kzalloc(&i2c->dev, |
@@ -139,7 +170,7 @@ static int max77693_i2c_probe(struct i2c_client *i2c, | |||
139 | return ret; | 170 | return ret; |
140 | } | 171 | } |
141 | 172 | ||
142 | ret = max77693_read_reg(max77693->regmap, MAX77693_PMIC_REG_PMIC_ID2, | 173 | ret = regmap_read(max77693->regmap, MAX77693_PMIC_REG_PMIC_ID2, |
143 | ®_data); | 174 | ®_data); |
144 | if (ret < 0) { | 175 | if (ret < 0) { |
145 | dev_err(max77693->dev, "device not found on this channel\n"); | 176 | dev_err(max77693->dev, "device not found on this channel\n"); |
@@ -176,9 +207,45 @@ static int max77693_i2c_probe(struct i2c_client *i2c, | |||
176 | goto err_regmap_muic; | 207 | goto err_regmap_muic; |
177 | } | 208 | } |
178 | 209 | ||
179 | ret = max77693_irq_init(max77693); | 210 | ret = regmap_add_irq_chip(max77693->regmap, max77693->irq, |
180 | if (ret < 0) | 211 | IRQF_ONESHOT | IRQF_SHARED | |
181 | goto err_irq; | 212 | IRQF_TRIGGER_FALLING, 0, |
213 | &max77693_led_irq_chip, | ||
214 | &max77693->irq_data_led); | ||
215 | if (ret) { | ||
216 | dev_err(max77693->dev, "failed to add irq chip: %d\n", ret); | ||
217 | goto err_regmap_muic; | ||
218 | } | ||
219 | |||
220 | ret = regmap_add_irq_chip(max77693->regmap, max77693->irq, | ||
221 | IRQF_ONESHOT | IRQF_SHARED | | ||
222 | IRQF_TRIGGER_FALLING, 0, | ||
223 | &max77693_topsys_irq_chip, | ||
224 | &max77693->irq_data_topsys); | ||
225 | if (ret) { | ||
226 | dev_err(max77693->dev, "failed to add irq chip: %d\n", ret); | ||
227 | goto err_irq_topsys; | ||
228 | } | ||
229 | |||
230 | ret = regmap_add_irq_chip(max77693->regmap, max77693->irq, | ||
231 | IRQF_ONESHOT | IRQF_SHARED | | ||
232 | IRQF_TRIGGER_FALLING, 0, | ||
233 | &max77693_charger_irq_chip, | ||
234 | &max77693->irq_data_charger); | ||
235 | if (ret) { | ||
236 | dev_err(max77693->dev, "failed to add irq chip: %d\n", ret); | ||
237 | goto err_irq_charger; | ||
238 | } | ||
239 | |||
240 | ret = regmap_add_irq_chip(max77693->regmap, max77693->irq, | ||
241 | IRQF_ONESHOT | IRQF_SHARED | | ||
242 | IRQF_TRIGGER_FALLING, 0, | ||
243 | &max77693_muic_irq_chip, | ||
244 | &max77693->irq_data_muic); | ||
245 | if (ret) { | ||
246 | dev_err(max77693->dev, "failed to add irq chip: %d\n", ret); | ||
247 | goto err_irq_muic; | ||
248 | } | ||
182 | 249 | ||
183 | pm_runtime_set_active(max77693->dev); | 250 | pm_runtime_set_active(max77693->dev); |
184 | 251 | ||
@@ -190,8 +257,14 @@ static int max77693_i2c_probe(struct i2c_client *i2c, | |||
190 | return ret; | 257 | return ret; |
191 | 258 | ||
192 | err_mfd: | 259 | err_mfd: |
193 | max77693_irq_exit(max77693); | 260 | mfd_remove_devices(max77693->dev); |
194 | err_irq: | 261 | regmap_del_irq_chip(max77693->irq, max77693->irq_data_muic); |
262 | err_irq_muic: | ||
263 | regmap_del_irq_chip(max77693->irq, max77693->irq_data_charger); | ||
264 | err_irq_charger: | ||
265 | regmap_del_irq_chip(max77693->irq, max77693->irq_data_topsys); | ||
266 | err_irq_topsys: | ||
267 | regmap_del_irq_chip(max77693->irq, max77693->irq_data_led); | ||
195 | err_regmap_muic: | 268 | err_regmap_muic: |
196 | i2c_unregister_device(max77693->haptic); | 269 | i2c_unregister_device(max77693->haptic); |
197 | err_i2c_haptic: | 270 | err_i2c_haptic: |
@@ -204,7 +277,12 @@ static int max77693_i2c_remove(struct i2c_client *i2c) | |||
204 | struct max77693_dev *max77693 = i2c_get_clientdata(i2c); | 277 | struct max77693_dev *max77693 = i2c_get_clientdata(i2c); |
205 | 278 | ||
206 | mfd_remove_devices(max77693->dev); | 279 | mfd_remove_devices(max77693->dev); |
207 | max77693_irq_exit(max77693); | 280 | |
281 | regmap_del_irq_chip(max77693->irq, max77693->irq_data_muic); | ||
282 | regmap_del_irq_chip(max77693->irq, max77693->irq_data_charger); | ||
283 | regmap_del_irq_chip(max77693->irq, max77693->irq_data_topsys); | ||
284 | regmap_del_irq_chip(max77693->irq, max77693->irq_data_led); | ||
285 | |||
208 | i2c_unregister_device(max77693->muic); | 286 | i2c_unregister_device(max77693->muic); |
209 | i2c_unregister_device(max77693->haptic); | 287 | i2c_unregister_device(max77693->haptic); |
210 | 288 | ||
@@ -222,8 +300,11 @@ static int max77693_suspend(struct device *dev) | |||
222 | struct i2c_client *i2c = container_of(dev, struct i2c_client, dev); | 300 | struct i2c_client *i2c = container_of(dev, struct i2c_client, dev); |
223 | struct max77693_dev *max77693 = i2c_get_clientdata(i2c); | 301 | struct max77693_dev *max77693 = i2c_get_clientdata(i2c); |
224 | 302 | ||
225 | if (device_may_wakeup(dev)) | 303 | if (device_may_wakeup(dev)) { |
226 | irq_set_irq_wake(max77693->irq, 1); | 304 | enable_irq_wake(max77693->irq); |
305 | disable_irq(max77693->irq); | ||
306 | } | ||
307 | |||
227 | return 0; | 308 | return 0; |
228 | } | 309 | } |
229 | 310 | ||
@@ -232,9 +313,12 @@ static int max77693_resume(struct device *dev) | |||
232 | struct i2c_client *i2c = container_of(dev, struct i2c_client, dev); | 313 | struct i2c_client *i2c = container_of(dev, struct i2c_client, dev); |
233 | struct max77693_dev *max77693 = i2c_get_clientdata(i2c); | 314 | struct max77693_dev *max77693 = i2c_get_clientdata(i2c); |
234 | 315 | ||
235 | if (device_may_wakeup(dev)) | 316 | if (device_may_wakeup(dev)) { |
236 | irq_set_irq_wake(max77693->irq, 0); | 317 | disable_irq_wake(max77693->irq); |
237 | return max77693_irq_resume(max77693); | 318 | enable_irq(max77693->irq); |
319 | } | ||
320 | |||
321 | return 0; | ||
238 | } | 322 | } |
239 | 323 | ||
240 | static const struct dev_pm_ops max77693_pm = { | 324 | static const struct dev_pm_ops max77693_pm = { |
diff --git a/drivers/regulator/max77693.c b/drivers/regulator/max77693.c index 653a58b49cdf..c67ff05fc1dd 100644 --- a/drivers/regulator/max77693.c +++ b/drivers/regulator/max77693.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include <linux/mfd/max77693.h> | 31 | #include <linux/mfd/max77693.h> |
32 | #include <linux/mfd/max77693-private.h> | 32 | #include <linux/mfd/max77693-private.h> |
33 | #include <linux/regulator/of_regulator.h> | 33 | #include <linux/regulator/of_regulator.h> |
34 | #include <linux/regmap.h> | ||
34 | 35 | ||
35 | #define CHGIN_ILIM_STEP_20mA 20000 | 36 | #define CHGIN_ILIM_STEP_20mA 20000 |
36 | 37 | ||
@@ -39,9 +40,9 @@ | |||
39 | static int max77693_chg_is_enabled(struct regulator_dev *rdev) | 40 | static int max77693_chg_is_enabled(struct regulator_dev *rdev) |
40 | { | 41 | { |
41 | int ret; | 42 | int ret; |
42 | u8 val; | 43 | unsigned int val; |
43 | 44 | ||
44 | ret = max77693_read_reg(rdev->regmap, rdev->desc->enable_reg, &val); | 45 | ret = regmap_read(rdev->regmap, rdev->desc->enable_reg, &val); |
45 | if (ret) | 46 | if (ret) |
46 | return ret; | 47 | return ret; |
47 | 48 | ||
@@ -57,12 +58,11 @@ static int max77693_chg_get_current_limit(struct regulator_dev *rdev) | |||
57 | { | 58 | { |
58 | unsigned int chg_min_uA = rdev->constraints->min_uA; | 59 | unsigned int chg_min_uA = rdev->constraints->min_uA; |
59 | unsigned int chg_max_uA = rdev->constraints->max_uA; | 60 | unsigned int chg_max_uA = rdev->constraints->max_uA; |
60 | u8 reg, sel; | 61 | unsigned int reg, sel; |
61 | unsigned int val; | 62 | unsigned int val; |
62 | int ret; | 63 | int ret; |
63 | 64 | ||
64 | ret = max77693_read_reg(rdev->regmap, | 65 | ret = regmap_read(rdev->regmap, MAX77693_CHG_REG_CHG_CNFG_09, ®); |
65 | MAX77693_CHG_REG_CHG_CNFG_09, ®); | ||
66 | if (ret < 0) | 66 | if (ret < 0) |
67 | return ret; | 67 | return ret; |
68 | 68 | ||
@@ -96,7 +96,7 @@ static int max77693_chg_set_current_limit(struct regulator_dev *rdev, | |||
96 | /* the first four codes for charger current are all 60mA */ | 96 | /* the first four codes for charger current are all 60mA */ |
97 | sel += 3; | 97 | sel += 3; |
98 | 98 | ||
99 | return max77693_write_reg(rdev->regmap, | 99 | return regmap_write(rdev->regmap, |
100 | MAX77693_CHG_REG_CHG_CNFG_09, sel); | 100 | MAX77693_CHG_REG_CHG_CNFG_09, sel); |
101 | } | 101 | } |
102 | /* end of CHARGER regulator ops */ | 102 | /* end of CHARGER regulator ops */ |
diff --git a/include/linux/extcon/sm5502.h b/include/linux/extcon/sm5502.h new file mode 100644 index 000000000000..030526bf8d79 --- /dev/null +++ b/include/linux/extcon/sm5502.h | |||
@@ -0,0 +1,287 @@ | |||
1 | /* | ||
2 | * sm5502.h | ||
3 | * | ||
4 | * Copyright (c) 2014 Samsung Electronics Co., Ltd | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of the GNU General Public License as published by the | ||
8 | * Free Software Foundation; either version 2 of the License, or (at your | ||
9 | * option) any later version. | ||
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 | #ifndef __LINUX_EXTCON_SM5502_H | ||
18 | #define __LINUX_EXTCON_SM5502_H | ||
19 | |||
20 | enum sm5502_types { | ||
21 | TYPE_SM5502, | ||
22 | }; | ||
23 | |||
24 | /* SM5502 registers */ | ||
25 | enum sm5502_reg { | ||
26 | SM5502_REG_DEVICE_ID = 0x01, | ||
27 | SM5502_REG_CONTROL, | ||
28 | SM5502_REG_INT1, | ||
29 | SM5502_REG_INT2, | ||
30 | SM5502_REG_INTMASK1, | ||
31 | SM5502_REG_INTMASK2, | ||
32 | SM5502_REG_ADC, | ||
33 | SM5502_REG_TIMING_SET1, | ||
34 | SM5502_REG_TIMING_SET2, | ||
35 | SM5502_REG_DEV_TYPE1, | ||
36 | SM5502_REG_DEV_TYPE2, | ||
37 | SM5502_REG_BUTTON1, | ||
38 | SM5502_REG_BUTTON2, | ||
39 | SM5502_REG_CAR_KIT_STATUS, | ||
40 | SM5502_REG_RSVD1, | ||
41 | SM5502_REG_RSVD2, | ||
42 | SM5502_REG_RSVD3, | ||
43 | SM5502_REG_RSVD4, | ||
44 | SM5502_REG_MANUAL_SW1, | ||
45 | SM5502_REG_MANUAL_SW2, | ||
46 | SM5502_REG_DEV_TYPE3, | ||
47 | SM5502_REG_RSVD5, | ||
48 | SM5502_REG_RSVD6, | ||
49 | SM5502_REG_RSVD7, | ||
50 | SM5502_REG_RSVD8, | ||
51 | SM5502_REG_RSVD9, | ||
52 | SM5502_REG_RESET, | ||
53 | SM5502_REG_RSVD10, | ||
54 | SM5502_REG_RESERVED_ID1, | ||
55 | SM5502_REG_RSVD11, | ||
56 | SM5502_REG_RSVD12, | ||
57 | SM5502_REG_RESERVED_ID2, | ||
58 | SM5502_REG_RSVD13, | ||
59 | SM5502_REG_OCP, | ||
60 | SM5502_REG_RSVD14, | ||
61 | SM5502_REG_RSVD15, | ||
62 | SM5502_REG_RSVD16, | ||
63 | SM5502_REG_RSVD17, | ||
64 | SM5502_REG_RSVD18, | ||
65 | SM5502_REG_RSVD19, | ||
66 | SM5502_REG_RSVD20, | ||
67 | SM5502_REG_RSVD21, | ||
68 | SM5502_REG_RSVD22, | ||
69 | SM5502_REG_RSVD23, | ||
70 | SM5502_REG_RSVD24, | ||
71 | SM5502_REG_RSVD25, | ||
72 | SM5502_REG_RSVD26, | ||
73 | SM5502_REG_RSVD27, | ||
74 | SM5502_REG_RSVD28, | ||
75 | SM5502_REG_RSVD29, | ||
76 | SM5502_REG_RSVD30, | ||
77 | SM5502_REG_RSVD31, | ||
78 | SM5502_REG_RSVD32, | ||
79 | SM5502_REG_RSVD33, | ||
80 | SM5502_REG_RSVD34, | ||
81 | SM5502_REG_RSVD35, | ||
82 | SM5502_REG_RSVD36, | ||
83 | SM5502_REG_RESERVED_ID3, | ||
84 | |||
85 | SM5502_REG_END, | ||
86 | }; | ||
87 | |||
88 | /* Define SM5502 MASK/SHIFT constant */ | ||
89 | #define SM5502_REG_DEVICE_ID_VENDOR_SHIFT 0 | ||
90 | #define SM5502_REG_DEVICE_ID_VERSION_SHIFT 3 | ||
91 | #define SM5502_REG_DEVICE_ID_VENDOR_MASK (0x3 << SM5502_REG_DEVICE_ID_VENDOR_SHIFT) | ||
92 | #define SM5502_REG_DEVICE_ID_VERSION_MASK (0x1f << SM5502_REG_DEVICE_ID_VERSION_SHIFT) | ||
93 | |||
94 | #define SM5502_REG_CONTROL_MASK_INT_SHIFT 0 | ||
95 | #define SM5502_REG_CONTROL_WAIT_SHIFT 1 | ||
96 | #define SM5502_REG_CONTROL_MANUAL_SW_SHIFT 2 | ||
97 | #define SM5502_REG_CONTROL_RAW_DATA_SHIFT 3 | ||
98 | #define SM5502_REG_CONTROL_SW_OPEN_SHIFT 4 | ||
99 | #define SM5502_REG_CONTROL_MASK_INT_MASK (0x1 << SM5502_REG_CONTROL_MASK_INT_SHIFT) | ||
100 | #define SM5502_REG_CONTROL_WAIT_MASK (0x1 << SM5502_REG_CONTROL_WAIT_SHIFT) | ||
101 | #define SM5502_REG_CONTROL_MANUAL_SW_MASK (0x1 << SM5502_REG_CONTROL_MANUAL_SW_SHIFT) | ||
102 | #define SM5502_REG_CONTROL_RAW_DATA_MASK (0x1 << SM5502_REG_CONTROL_RAW_DATA_SHIFT) | ||
103 | #define SM5502_REG_CONTROL_SW_OPEN_MASK (0x1 << SM5502_REG_CONTROL_SW_OPEN_SHIFT) | ||
104 | |||
105 | #define SM5502_REG_INTM1_ATTACH_SHIFT 0 | ||
106 | #define SM5502_REG_INTM1_DETACH_SHIFT 1 | ||
107 | #define SM5502_REG_INTM1_KP_SHIFT 2 | ||
108 | #define SM5502_REG_INTM1_LKP_SHIFT 3 | ||
109 | #define SM5502_REG_INTM1_LKR_SHIFT 4 | ||
110 | #define SM5502_REG_INTM1_OVP_EVENT_SHIFT 5 | ||
111 | #define SM5502_REG_INTM1_OCP_EVENT_SHIFT 6 | ||
112 | #define SM5502_REG_INTM1_OVP_OCP_DIS_SHIFT 7 | ||
113 | #define SM5502_REG_INTM1_ATTACH_MASK (0x1 << SM5502_REG_INTM1_ATTACH_SHIFT) | ||
114 | #define SM5502_REG_INTM1_DETACH_MASK (0x1 << SM5502_REG_INTM1_DETACH_SHIFT) | ||
115 | #define SM5502_REG_INTM1_KP_MASK (0x1 << SM5502_REG_INTM1_KP_SHIFT) | ||
116 | #define SM5502_REG_INTM1_LKP_MASK (0x1 << SM5502_REG_INTM1_LKP_SHIFT) | ||
117 | #define SM5502_REG_INTM1_LKR_MASK (0x1 << SM5502_REG_INTM1_LKR_SHIFT) | ||
118 | #define SM5502_REG_INTM1_OVP_EVENT_MASK (0x1 << SM5502_REG_INTM1_OVP_EVENT_SHIFT) | ||
119 | #define SM5502_REG_INTM1_OCP_EVENT_MASK (0x1 << SM5502_REG_INTM1_OCP_EVENT_SHIFT) | ||
120 | #define SM5502_REG_INTM1_OVP_OCP_DIS_MASK (0x1 << SM5502_REG_INTM1_OVP_OCP_DIS_SHIFT) | ||
121 | |||
122 | #define SM5502_REG_INTM2_VBUS_DET_SHIFT 0 | ||
123 | #define SM5502_REG_INTM2_REV_ACCE_SHIFT 1 | ||
124 | #define SM5502_REG_INTM2_ADC_CHG_SHIFT 2 | ||
125 | #define SM5502_REG_INTM2_STUCK_KEY_SHIFT 3 | ||
126 | #define SM5502_REG_INTM2_STUCK_KEY_RCV_SHIFT 4 | ||
127 | #define SM5502_REG_INTM2_MHL_SHIFT 5 | ||
128 | #define SM5502_REG_INTM2_VBUS_DET_MASK (0x1 << SM5502_REG_INTM2_VBUS_DET_SHIFT) | ||
129 | #define SM5502_REG_INTM2_REV_ACCE_MASK (0x1 << SM5502_REG_INTM2_REV_ACCE_SHIFT) | ||
130 | #define SM5502_REG_INTM2_ADC_CHG_MASK (0x1 << SM5502_REG_INTM2_ADC_CHG_SHIFT) | ||
131 | #define SM5502_REG_INTM2_STUCK_KEY_MASK (0x1 << SM5502_REG_INTM2_STUCK_KEY_SHIFT) | ||
132 | #define SM5502_REG_INTM2_STUCK_KEY_RCV_MASK (0x1 << SM5502_REG_INTM2_STUCK_KEY_RCV_SHIFT) | ||
133 | #define SM5502_REG_INTM2_MHL_MASK (0x1 << SM5502_REG_INTM2_MHL_SHIFT) | ||
134 | |||
135 | #define SM5502_REG_ADC_SHIFT 0 | ||
136 | #define SM5502_REG_ADC_MASK (0x1f << SM5502_REG_ADC_SHIFT) | ||
137 | |||
138 | #define SM5502_REG_TIMING_SET1_KEY_PRESS_SHIFT 4 | ||
139 | #define SM5502_REG_TIMING_SET1_KEY_PRESS_MASK (0xf << SM5502_REG_TIMING_SET1_KEY_PRESS_SHIFT) | ||
140 | #define TIMING_KEY_PRESS_100MS 0x0 | ||
141 | #define TIMING_KEY_PRESS_200MS 0x1 | ||
142 | #define TIMING_KEY_PRESS_300MS 0x2 | ||
143 | #define TIMING_KEY_PRESS_400MS 0x3 | ||
144 | #define TIMING_KEY_PRESS_500MS 0x4 | ||
145 | #define TIMING_KEY_PRESS_600MS 0x5 | ||
146 | #define TIMING_KEY_PRESS_700MS 0x6 | ||
147 | #define TIMING_KEY_PRESS_800MS 0x7 | ||
148 | #define TIMING_KEY_PRESS_900MS 0x8 | ||
149 | #define TIMING_KEY_PRESS_1000MS 0x9 | ||
150 | #define SM5502_REG_TIMING_SET1_ADC_DET_SHIFT 0 | ||
151 | #define SM5502_REG_TIMING_SET1_ADC_DET_MASK (0xf << SM5502_REG_TIMING_SET1_ADC_DET_SHIFT) | ||
152 | #define TIMING_ADC_DET_50MS 0x0 | ||
153 | #define TIMING_ADC_DET_100MS 0x1 | ||
154 | #define TIMING_ADC_DET_150MS 0x2 | ||
155 | #define TIMING_ADC_DET_200MS 0x3 | ||
156 | #define TIMING_ADC_DET_300MS 0x4 | ||
157 | #define TIMING_ADC_DET_400MS 0x5 | ||
158 | #define TIMING_ADC_DET_500MS 0x6 | ||
159 | #define TIMING_ADC_DET_600MS 0x7 | ||
160 | #define TIMING_ADC_DET_700MS 0x8 | ||
161 | #define TIMING_ADC_DET_800MS 0x9 | ||
162 | #define TIMING_ADC_DET_900MS 0xA | ||
163 | #define TIMING_ADC_DET_1000MS 0xB | ||
164 | |||
165 | #define SM5502_REG_TIMING_SET2_SW_WAIT_SHIFT 4 | ||
166 | #define SM5502_REG_TIMING_SET2_SW_WAIT_MASK (0xf << SM5502_REG_TIMING_SET2_SW_WAIT_SHIFT) | ||
167 | #define TIMING_SW_WAIT_10MS 0x0 | ||
168 | #define TIMING_SW_WAIT_30MS 0x1 | ||
169 | #define TIMING_SW_WAIT_50MS 0x2 | ||
170 | #define TIMING_SW_WAIT_70MS 0x3 | ||
171 | #define TIMING_SW_WAIT_90MS 0x4 | ||
172 | #define TIMING_SW_WAIT_110MS 0x5 | ||
173 | #define TIMING_SW_WAIT_130MS 0x6 | ||
174 | #define TIMING_SW_WAIT_150MS 0x7 | ||
175 | #define TIMING_SW_WAIT_170MS 0x8 | ||
176 | #define TIMING_SW_WAIT_190MS 0x9 | ||
177 | #define TIMING_SW_WAIT_210MS 0xA | ||
178 | #define SM5502_REG_TIMING_SET2_LONG_KEY_SHIFT 0 | ||
179 | #define SM5502_REG_TIMING_SET2_LONG_KEY_MASK (0xf << SM5502_REG_TIMING_SET2_LONG_KEY_SHIFT) | ||
180 | #define TIMING_LONG_KEY_300MS 0x0 | ||
181 | #define TIMING_LONG_KEY_400MS 0x1 | ||
182 | #define TIMING_LONG_KEY_500MS 0x2 | ||
183 | #define TIMING_LONG_KEY_600MS 0x3 | ||
184 | #define TIMING_LONG_KEY_700MS 0x4 | ||
185 | #define TIMING_LONG_KEY_800MS 0x5 | ||
186 | #define TIMING_LONG_KEY_900MS 0x6 | ||
187 | #define TIMING_LONG_KEY_1000MS 0x7 | ||
188 | #define TIMING_LONG_KEY_1100MS 0x8 | ||
189 | #define TIMING_LONG_KEY_1200MS 0x9 | ||
190 | #define TIMING_LONG_KEY_1300MS 0xA | ||
191 | #define TIMING_LONG_KEY_1400MS 0xB | ||
192 | #define TIMING_LONG_KEY_1500MS 0xC | ||
193 | |||
194 | #define SM5502_REG_DEV_TYPE1_AUDIO_TYPE1_SHIFT 0 | ||
195 | #define SM5502_REG_DEV_TYPE1_AUDIO_TYPE2_SHIFT 1 | ||
196 | #define SM5502_REG_DEV_TYPE1_USB_SDP_SHIFT 2 | ||
197 | #define SM5502_REG_DEV_TYPE1_UART_SHIFT 3 | ||
198 | #define SM5502_REG_DEV_TYPE1_CAR_KIT_CHARGER_SHIFT 4 | ||
199 | #define SM5502_REG_DEV_TYPE1_USB_CHG_SHIFT 5 | ||
200 | #define SM5502_REG_DEV_TYPE1_DEDICATED_CHG_SHIFT 6 | ||
201 | #define SM5502_REG_DEV_TYPE1_USB_OTG_SHIFT 7 | ||
202 | #define SM5502_REG_DEV_TYPE1_AUDIO_TYPE1_MASK (0x1 << SM5502_REG_DEV_TYPE1_AUDIO_TYPE1_SHIFT) | ||
203 | #define SM5502_REG_DEV_TYPE1_AUDIO_TYPE1__MASK (0x1 << SM5502_REG_DEV_TYPE1_AUDIO_TYPE2_SHIFT) | ||
204 | #define SM5502_REG_DEV_TYPE1_USB_SDP_MASK (0x1 << SM5502_REG_DEV_TYPE1_USB_SDP_SHIFT) | ||
205 | #define SM5502_REG_DEV_TYPE1_UART_MASK (0x1 << SM5502_REG_DEV_TYPE1_UART_SHIFT) | ||
206 | #define SM5502_REG_DEV_TYPE1_CAR_KIT_CHARGER_MASK (0x1 << SM5502_REG_DEV_TYPE1_CAR_KIT_CHARGER_SHIFT) | ||
207 | #define SM5502_REG_DEV_TYPE1_USB_CHG_MASK (0x1 << SM5502_REG_DEV_TYPE1_USB_CHG_SHIFT) | ||
208 | #define SM5502_REG_DEV_TYPE1_DEDICATED_CHG_MASK (0x1 << SM5502_REG_DEV_TYPE1_DEDICATED_CHG_SHIFT) | ||
209 | #define SM5502_REG_DEV_TYPE1_USB_OTG_MASK (0x1 << SM5502_REG_DEV_TYPE1_USB_OTG_SHIFT) | ||
210 | |||
211 | #define SM5502_REG_DEV_TYPE2_JIG_USB_ON_SHIFT 0 | ||
212 | #define SM5502_REG_DEV_TYPE2_JIG_USB_OFF_SHIFT 1 | ||
213 | #define SM5502_REG_DEV_TYPE2_JIG_UART_ON_SHIFT 2 | ||
214 | #define SM5502_REG_DEV_TYPE2_JIG_UART_OFF_SHIFT 3 | ||
215 | #define SM5502_REG_DEV_TYPE2_PPD_SHIFT 4 | ||
216 | #define SM5502_REG_DEV_TYPE2_TTY_SHIFT 5 | ||
217 | #define SM5502_REG_DEV_TYPE2_AV_CABLE_SHIFT 6 | ||
218 | #define SM5502_REG_DEV_TYPE2_JIG_USB_ON_MASK (0x1 << SM5502_REG_DEV_TYPE2_JIG_USB_ON_SHIFT) | ||
219 | #define SM5502_REG_DEV_TYPE2_JIG_USB_OFF_MASK (0x1 << SM5502_REG_DEV_TYPE2_JIG_USB_OFF_SHIFT) | ||
220 | #define SM5502_REG_DEV_TYPE2_JIG_UART_ON_MASK (0x1 << SM5502_REG_DEV_TYPE2_JIG_UART_ON_SHIFT) | ||
221 | #define SM5502_REG_DEV_TYPE2_JIG_UART_OFF_MASK (0x1 << SM5502_REG_DEV_TYPE2_JIG_UART_OFF_SHIFT) | ||
222 | #define SM5502_REG_DEV_TYPE2_PPD_MASK (0x1 << SM5502_REG_DEV_TYPE2_PPD_SHIFT) | ||
223 | #define SM5502_REG_DEV_TYPE2_TTY_MASK (0x1 << SM5502_REG_DEV_TYPE2_TTY_SHIFT) | ||
224 | #define SM5502_REG_DEV_TYPE2_AV_CABLE_MASK (0x1 << SM5502_REG_DEV_TYPE2_AV_CABLE_SHIFT) | ||
225 | |||
226 | #define SM5502_REG_MANUAL_SW1_VBUSIN_SHIFT 0 | ||
227 | #define SM5502_REG_MANUAL_SW1_DP_SHIFT 2 | ||
228 | #define SM5502_REG_MANUAL_SW1_DM_SHIFT 5 | ||
229 | #define SM5502_REG_MANUAL_SW1_VBUSIN_MASK (0x3 << SM5502_REG_MANUAL_SW1_VBUSIN_SHIFT) | ||
230 | #define SM5502_REG_MANUAL_SW1_DP_MASK (0x7 << SM5502_REG_MANUAL_SW1_DP_SHIFT) | ||
231 | #define SM5502_REG_MANUAL_SW1_DM_MASK (0x7 << SM5502_REG_MANUAL_SW1_DM_SHIFT) | ||
232 | #define VBUSIN_SWITCH_OPEN 0x0 | ||
233 | #define VBUSIN_SWITCH_VBUSOUT 0x1 | ||
234 | #define VBUSIN_SWITCH_MIC 0x2 | ||
235 | #define VBUSIN_SWITCH_VBUSOUT_WITH_USB 0x3 | ||
236 | #define DM_DP_CON_SWITCH_OPEN 0x0 | ||
237 | #define DM_DP_CON_SWITCH_USB 0x1 | ||
238 | #define DM_DP_CON_SWITCH_AUDIO 0x2 | ||
239 | #define DM_DP_CON_SWITCH_UART 0x3 | ||
240 | #define DM_DP_SWITCH_OPEN ((DM_DP_CON_SWITCH_OPEN <<SM5502_REG_MANUAL_SW1_DP_SHIFT) \ | ||
241 | | (DM_DP_CON_SWITCH_OPEN <<SM5502_REG_MANUAL_SW1_DM_SHIFT)) | ||
242 | #define DM_DP_SWITCH_USB ((DM_DP_CON_SWITCH_USB <<SM5502_REG_MANUAL_SW1_DP_SHIFT) \ | ||
243 | | (DM_DP_CON_SWITCH_USB <<SM5502_REG_MANUAL_SW1_DM_SHIFT)) | ||
244 | #define DM_DP_SWITCH_AUDIO ((DM_DP_CON_SWITCH_AUDIO <<SM5502_REG_MANUAL_SW1_DP_SHIFT) \ | ||
245 | | (DM_DP_CON_SWITCH_AUDIO <<SM5502_REG_MANUAL_SW1_DM_SHIFT)) | ||
246 | #define DM_DP_SWITCH_UART ((DM_DP_CON_SWITCH_UART <<SM5502_REG_MANUAL_SW1_DP_SHIFT) \ | ||
247 | | (DM_DP_CON_SWITCH_UART <<SM5502_REG_MANUAL_SW1_DM_SHIFT)) | ||
248 | |||
249 | /* SM5502 Interrupts */ | ||
250 | enum sm5502_irq { | ||
251 | /* INT1 */ | ||
252 | SM5502_IRQ_INT1_ATTACH, | ||
253 | SM5502_IRQ_INT1_DETACH, | ||
254 | SM5502_IRQ_INT1_KP, | ||
255 | SM5502_IRQ_INT1_LKP, | ||
256 | SM5502_IRQ_INT1_LKR, | ||
257 | SM5502_IRQ_INT1_OVP_EVENT, | ||
258 | SM5502_IRQ_INT1_OCP_EVENT, | ||
259 | SM5502_IRQ_INT1_OVP_OCP_DIS, | ||
260 | |||
261 | /* INT2 */ | ||
262 | SM5502_IRQ_INT2_VBUS_DET, | ||
263 | SM5502_IRQ_INT2_REV_ACCE, | ||
264 | SM5502_IRQ_INT2_ADC_CHG, | ||
265 | SM5502_IRQ_INT2_STUCK_KEY, | ||
266 | SM5502_IRQ_INT2_STUCK_KEY_RCV, | ||
267 | SM5502_IRQ_INT2_MHL, | ||
268 | |||
269 | SM5502_IRQ_NUM, | ||
270 | }; | ||
271 | |||
272 | #define SM5502_IRQ_INT1_ATTACH_MASK BIT(0) | ||
273 | #define SM5502_IRQ_INT1_DETACH_MASK BIT(1) | ||
274 | #define SM5502_IRQ_INT1_KP_MASK BIT(2) | ||
275 | #define SM5502_IRQ_INT1_LKP_MASK BIT(3) | ||
276 | #define SM5502_IRQ_INT1_LKR_MASK BIT(4) | ||
277 | #define SM5502_IRQ_INT1_OVP_EVENT_MASK BIT(5) | ||
278 | #define SM5502_IRQ_INT1_OCP_EVENT_MASK BIT(6) | ||
279 | #define SM5502_IRQ_INT1_OVP_OCP_DIS_MASK BIT(7) | ||
280 | #define SM5502_IRQ_INT2_VBUS_DET_MASK BIT(0) | ||
281 | #define SM5502_IRQ_INT2_REV_ACCE_MASK BIT(1) | ||
282 | #define SM5502_IRQ_INT2_ADC_CHG_MASK BIT(2) | ||
283 | #define SM5502_IRQ_INT2_STUCK_KEY_MASK BIT(3) | ||
284 | #define SM5502_IRQ_INT2_STUCK_KEY_RCV_MASK BIT(4) | ||
285 | #define SM5502_IRQ_INT2_MHL_MASK BIT(5) | ||
286 | |||
287 | #endif /* __LINUX_EXTCON_SM5502_H */ | ||
diff --git a/include/linux/mfd/arizona/pdata.h b/include/linux/mfd/arizona/pdata.h index 12a5c135c746..4578c72c9b86 100644 --- a/include/linux/mfd/arizona/pdata.h +++ b/include/linux/mfd/arizona/pdata.h | |||
@@ -127,6 +127,9 @@ struct arizona_pdata { | |||
127 | /** Internal pull on GPIO5 is disabled when used for jack detection */ | 127 | /** Internal pull on GPIO5 is disabled when used for jack detection */ |
128 | bool jd_gpio5_nopull; | 128 | bool jd_gpio5_nopull; |
129 | 129 | ||
130 | /** set to true if jackdet contact opens on insert */ | ||
131 | bool jd_invert; | ||
132 | |||
130 | /** Use the headphone detect circuit to identify the accessory */ | 133 | /** Use the headphone detect circuit to identify the accessory */ |
131 | bool hpdet_acc_id; | 134 | bool hpdet_acc_id; |
132 | 135 | ||
diff --git a/include/linux/mfd/max77693-private.h b/include/linux/mfd/max77693-private.h index 3e050b933dd0..c466ff3e16b8 100644 --- a/include/linux/mfd/max77693-private.h +++ b/include/linux/mfd/max77693-private.h | |||
@@ -262,6 +262,41 @@ enum max77693_irq_source { | |||
262 | MAX77693_IRQ_GROUP_NR, | 262 | MAX77693_IRQ_GROUP_NR, |
263 | }; | 263 | }; |
264 | 264 | ||
265 | #define LED_IRQ_FLED2_OPEN BIT(0) | ||
266 | #define LED_IRQ_FLED2_SHORT BIT(1) | ||
267 | #define LED_IRQ_FLED1_OPEN BIT(2) | ||
268 | #define LED_IRQ_FLED1_SHORT BIT(3) | ||
269 | #define LED_IRQ_MAX_FLASH BIT(4) | ||
270 | |||
271 | #define TOPSYS_IRQ_T120C_INT BIT(0) | ||
272 | #define TOPSYS_IRQ_T140C_INT BIT(1) | ||
273 | #define TOPSYS_IRQ_LOWSYS_INT BIT(3) | ||
274 | |||
275 | #define CHG_IRQ_BYP_I BIT(0) | ||
276 | #define CHG_IRQ_THM_I BIT(2) | ||
277 | #define CHG_IRQ_BAT_I BIT(3) | ||
278 | #define CHG_IRQ_CHG_I BIT(4) | ||
279 | #define CHG_IRQ_CHGIN_I BIT(6) | ||
280 | |||
281 | #define MUIC_IRQ_INT1_ADC BIT(0) | ||
282 | #define MUIC_IRQ_INT1_ADC_LOW BIT(1) | ||
283 | #define MUIC_IRQ_INT1_ADC_ERR BIT(2) | ||
284 | #define MUIC_IRQ_INT1_ADC1K BIT(3) | ||
285 | |||
286 | #define MUIC_IRQ_INT2_CHGTYP BIT(0) | ||
287 | #define MUIC_IRQ_INT2_CHGDETREUN BIT(1) | ||
288 | #define MUIC_IRQ_INT2_DCDTMR BIT(2) | ||
289 | #define MUIC_IRQ_INT2_DXOVP BIT(3) | ||
290 | #define MUIC_IRQ_INT2_VBVOLT BIT(4) | ||
291 | #define MUIC_IRQ_INT2_VIDRM BIT(5) | ||
292 | |||
293 | #define MUIC_IRQ_INT3_EOC BIT(0) | ||
294 | #define MUIC_IRQ_INT3_CGMBC BIT(1) | ||
295 | #define MUIC_IRQ_INT3_OVP BIT(2) | ||
296 | #define MUIC_IRQ_INT3_MBCCHG_ERR BIT(3) | ||
297 | #define MUIC_IRQ_INT3_CHG_ENABLED BIT(4) | ||
298 | #define MUIC_IRQ_INT3_BAT_DET BIT(5) | ||
299 | |||
265 | enum max77693_irq { | 300 | enum max77693_irq { |
266 | /* PMIC - FLASH */ | 301 | /* PMIC - FLASH */ |
267 | MAX77693_LED_IRQ_FLED2_OPEN, | 302 | MAX77693_LED_IRQ_FLED2_OPEN, |
@@ -282,6 +317,10 @@ enum max77693_irq { | |||
282 | MAX77693_CHG_IRQ_CHG_I, | 317 | MAX77693_CHG_IRQ_CHG_I, |
283 | MAX77693_CHG_IRQ_CHGIN_I, | 318 | MAX77693_CHG_IRQ_CHGIN_I, |
284 | 319 | ||
320 | MAX77693_IRQ_NR, | ||
321 | }; | ||
322 | |||
323 | enum max77693_irq_muic { | ||
285 | /* MUIC INT1 */ | 324 | /* MUIC INT1 */ |
286 | MAX77693_MUIC_IRQ_INT1_ADC, | 325 | MAX77693_MUIC_IRQ_INT1_ADC, |
287 | MAX77693_MUIC_IRQ_INT1_ADC_LOW, | 326 | MAX77693_MUIC_IRQ_INT1_ADC_LOW, |
@@ -304,7 +343,7 @@ enum max77693_irq { | |||
304 | MAX77693_MUIC_IRQ_INT3_CHG_ENABLED, | 343 | MAX77693_MUIC_IRQ_INT3_CHG_ENABLED, |
305 | MAX77693_MUIC_IRQ_INT3_BAT_DET, | 344 | MAX77693_MUIC_IRQ_INT3_BAT_DET, |
306 | 345 | ||
307 | MAX77693_IRQ_NR, | 346 | MAX77693_MUIC_IRQ_NR, |
308 | }; | 347 | }; |
309 | 348 | ||
310 | struct max77693_dev { | 349 | struct max77693_dev { |
@@ -319,7 +358,10 @@ struct max77693_dev { | |||
319 | struct regmap *regmap_muic; | 358 | struct regmap *regmap_muic; |
320 | struct regmap *regmap_haptic; | 359 | struct regmap *regmap_haptic; |
321 | 360 | ||
322 | struct irq_domain *irq_domain; | 361 | struct regmap_irq_chip_data *irq_data_led; |
362 | struct regmap_irq_chip_data *irq_data_topsys; | ||
363 | struct regmap_irq_chip_data *irq_data_charger; | ||
364 | struct regmap_irq_chip_data *irq_data_muic; | ||
323 | 365 | ||
324 | int irq; | 366 | int irq; |
325 | int irq_gpio; | 367 | int irq_gpio; |
@@ -332,14 +374,6 @@ enum max77693_types { | |||
332 | TYPE_MAX77693, | 374 | TYPE_MAX77693, |
333 | }; | 375 | }; |
334 | 376 | ||
335 | extern int max77693_read_reg(struct regmap *map, u8 reg, u8 *dest); | ||
336 | extern int max77693_bulk_read(struct regmap *map, u8 reg, int count, | ||
337 | u8 *buf); | ||
338 | extern int max77693_write_reg(struct regmap *map, u8 reg, u8 value); | ||
339 | extern int max77693_bulk_write(struct regmap *map, u8 reg, int count, | ||
340 | u8 *buf); | ||
341 | extern int max77693_update_reg(struct regmap *map, u8 reg, u8 val, u8 mask); | ||
342 | |||
343 | extern int max77693_irq_init(struct max77693_dev *max77686); | 377 | extern int max77693_irq_init(struct max77693_dev *max77686); |
344 | extern void max77693_irq_exit(struct max77693_dev *max77686); | 378 | extern void max77693_irq_exit(struct max77693_dev *max77686); |
345 | extern int max77693_irq_resume(struct max77693_dev *max77686); | 379 | extern int max77693_irq_resume(struct max77693_dev *max77686); |