diff options
author | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2015-08-17 12:12:15 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2015-08-17 12:12:15 -0400 |
commit | 672cfeeb93e572f108965cf964c3e2a869a549cc (patch) | |
tree | 22db36d19e7292c9ddbcb486049e893017c278ff | |
parent | 92f26189b181a65fcb1ff6220a4bf45d44502e4a (diff) | |
parent | ac22a1d3386e195c57e299da3bfad97a061b9616 (diff) |
Merge tag 'extcon-next-for-4.3' of git://git.kernel.org/pub/scm/linux/kernel/git/chanwoo/extcon into char-misc-testing
Chanwoo writes:
Update extcon for v4.3
This patchset include the function update of extcon drivers without critical
update and fix minor issue of extcon drivers.
Detailed description for patchset:
1. Update the extcon drivers:
- Update the logic of microphone detection for extcon-arizona driver
- Support GPIO based USB ID detection of extcon-palmas driver
2. Fix minor issues:
- Clean code and remove the opitonal print_state() function pointer from extcon
core driver
- Clear interrupt bit state before requesting irq on extcon-max778433 driver
- Fix signedness bugs of extcon core driver
-rw-r--r-- | Documentation/devicetree/bindings/extcon/extcon-palmas.txt | 5 | ||||
-rw-r--r-- | drivers/extcon/extcon-arizona.c | 101 | ||||
-rw-r--r-- | drivers/extcon/extcon-gpio.c | 18 | ||||
-rw-r--r-- | drivers/extcon/extcon-max77843.c | 9 | ||||
-rw-r--r-- | drivers/extcon/extcon-palmas.c | 134 | ||||
-rw-r--r-- | drivers/extcon/extcon-rt8973a.c | 1 | ||||
-rw-r--r-- | drivers/extcon/extcon-sm5502.c | 1 | ||||
-rw-r--r-- | drivers/extcon/extcon-usb-gpio.c | 1 | ||||
-rw-r--r-- | drivers/extcon/extcon.c | 48 | ||||
-rw-r--r-- | include/linux/extcon.h | 7 | ||||
-rw-r--r-- | include/linux/mfd/palmas.h | 7 |
11 files changed, 255 insertions, 77 deletions
diff --git a/Documentation/devicetree/bindings/extcon/extcon-palmas.txt b/Documentation/devicetree/bindings/extcon/extcon-palmas.txt index 45414bbcd945..f61d5af44a27 100644 --- a/Documentation/devicetree/bindings/extcon/extcon-palmas.txt +++ b/Documentation/devicetree/bindings/extcon/extcon-palmas.txt | |||
@@ -10,8 +10,11 @@ Required Properties: | |||
10 | 10 | ||
11 | Optional Properties: | 11 | Optional Properties: |
12 | - ti,wakeup : To enable the wakeup comparator in probe | 12 | - ti,wakeup : To enable the wakeup comparator in probe |
13 | - ti,enable-id-detection: Perform ID detection. | 13 | - ti,enable-id-detection: Perform ID detection. If id-gpio is specified |
14 | it performs id-detection using GPIO else using OTG core. | ||
14 | - ti,enable-vbus-detection: Perform VBUS detection. | 15 | - ti,enable-vbus-detection: Perform VBUS detection. |
16 | - id-gpio: gpio for GPIO ID detection. See gpio binding. | ||
17 | - debounce-delay-ms: debounce delay for GPIO ID pin in milliseconds. | ||
15 | 18 | ||
16 | palmas-usb { | 19 | palmas-usb { |
17 | compatible = "ti,twl6035-usb", "ti,palmas-usb"; | 20 | compatible = "ti,twl6035-usb", "ti,palmas-usb"; |
diff --git a/drivers/extcon/extcon-arizona.c b/drivers/extcon/extcon-arizona.c index ad87f263056f..4b9f09cc38d8 100644 --- a/drivers/extcon/extcon-arizona.c +++ b/drivers/extcon/extcon-arizona.c | |||
@@ -20,10 +20,12 @@ | |||
20 | #include <linux/slab.h> | 20 | #include <linux/slab.h> |
21 | #include <linux/interrupt.h> | 21 | #include <linux/interrupt.h> |
22 | #include <linux/err.h> | 22 | #include <linux/err.h> |
23 | #include <linux/gpio/consumer.h> | ||
23 | #include <linux/gpio.h> | 24 | #include <linux/gpio.h> |
24 | #include <linux/input.h> | 25 | #include <linux/input.h> |
25 | #include <linux/platform_device.h> | 26 | #include <linux/platform_device.h> |
26 | #include <linux/pm_runtime.h> | 27 | #include <linux/pm_runtime.h> |
28 | #include <linux/property.h> | ||
27 | #include <linux/regulator/consumer.h> | 29 | #include <linux/regulator/consumer.h> |
28 | #include <linux/extcon.h> | 30 | #include <linux/extcon.h> |
29 | 31 | ||
@@ -46,6 +48,9 @@ | |||
46 | #define HPDET_DEBOUNCE 500 | 48 | #define HPDET_DEBOUNCE 500 |
47 | #define DEFAULT_MICD_TIMEOUT 2000 | 49 | #define DEFAULT_MICD_TIMEOUT 2000 |
48 | 50 | ||
51 | #define MICD_DBTIME_TWO_READINGS 2 | ||
52 | #define MICD_DBTIME_FOUR_READINGS 4 | ||
53 | |||
49 | #define MICD_LVL_1_TO_7 (ARIZONA_MICD_LVL_1 | ARIZONA_MICD_LVL_2 | \ | 54 | #define MICD_LVL_1_TO_7 (ARIZONA_MICD_LVL_1 | ARIZONA_MICD_LVL_2 | \ |
50 | ARIZONA_MICD_LVL_3 | ARIZONA_MICD_LVL_4 | \ | 55 | ARIZONA_MICD_LVL_3 | ARIZONA_MICD_LVL_4 | \ |
51 | ARIZONA_MICD_LVL_5 | ARIZONA_MICD_LVL_6 | \ | 56 | ARIZONA_MICD_LVL_5 | ARIZONA_MICD_LVL_6 | \ |
@@ -94,6 +99,8 @@ struct arizona_extcon_info { | |||
94 | int hpdet_ip_version; | 99 | int hpdet_ip_version; |
95 | 100 | ||
96 | struct extcon_dev *edev; | 101 | struct extcon_dev *edev; |
102 | |||
103 | struct gpio_desc *micd_pol_gpio; | ||
97 | }; | 104 | }; |
98 | 105 | ||
99 | static const struct arizona_micd_config micd_default_modes[] = { | 106 | static const struct arizona_micd_config micd_default_modes[] = { |
@@ -204,6 +211,10 @@ static void arizona_extcon_set_mode(struct arizona_extcon_info *info, int mode) | |||
204 | if (arizona->pdata.micd_pol_gpio > 0) | 211 | if (arizona->pdata.micd_pol_gpio > 0) |
205 | gpio_set_value_cansleep(arizona->pdata.micd_pol_gpio, | 212 | gpio_set_value_cansleep(arizona->pdata.micd_pol_gpio, |
206 | info->micd_modes[mode].gpio); | 213 | info->micd_modes[mode].gpio); |
214 | else | ||
215 | gpiod_set_value_cansleep(info->micd_pol_gpio, | ||
216 | info->micd_modes[mode].gpio); | ||
217 | |||
207 | regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1, | 218 | regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1, |
208 | ARIZONA_MICD_BIAS_SRC_MASK, | 219 | ARIZONA_MICD_BIAS_SRC_MASK, |
209 | info->micd_modes[mode].bias << | 220 | info->micd_modes[mode].bias << |
@@ -757,10 +768,11 @@ static void arizona_micd_timeout_work(struct work_struct *work) | |||
757 | mutex_lock(&info->lock); | 768 | mutex_lock(&info->lock); |
758 | 769 | ||
759 | dev_dbg(info->arizona->dev, "MICD timed out, reporting HP\n"); | 770 | dev_dbg(info->arizona->dev, "MICD timed out, reporting HP\n"); |
760 | arizona_identify_headphone(info); | ||
761 | 771 | ||
762 | info->detecting = false; | 772 | info->detecting = false; |
763 | 773 | ||
774 | arizona_identify_headphone(info); | ||
775 | |||
764 | arizona_stop_mic(info); | 776 | arizona_stop_mic(info); |
765 | 777 | ||
766 | mutex_unlock(&info->lock); | 778 | mutex_unlock(&info->lock); |
@@ -820,12 +832,18 @@ static void arizona_micd_detect(struct work_struct *work) | |||
820 | /* Due to jack detect this should never happen */ | 832 | /* Due to jack detect this should never happen */ |
821 | if (!(val & ARIZONA_MICD_STS)) { | 833 | if (!(val & ARIZONA_MICD_STS)) { |
822 | dev_warn(arizona->dev, "Detected open circuit\n"); | 834 | dev_warn(arizona->dev, "Detected open circuit\n"); |
835 | info->mic = false; | ||
836 | arizona_stop_mic(info); | ||
823 | info->detecting = false; | 837 | info->detecting = false; |
838 | arizona_identify_headphone(info); | ||
824 | goto handled; | 839 | goto handled; |
825 | } | 840 | } |
826 | 841 | ||
827 | /* If we got a high impedence we should have a headset, report it. */ | 842 | /* If we got a high impedence we should have a headset, report it. */ |
828 | if (info->detecting && (val & ARIZONA_MICD_LVL_8)) { | 843 | if (info->detecting && (val & ARIZONA_MICD_LVL_8)) { |
844 | info->mic = true; | ||
845 | info->detecting = false; | ||
846 | |||
829 | arizona_identify_headphone(info); | 847 | arizona_identify_headphone(info); |
830 | 848 | ||
831 | ret = extcon_set_cable_state_(info->edev, | 849 | ret = extcon_set_cable_state_(info->edev, |
@@ -841,8 +859,6 @@ static void arizona_micd_detect(struct work_struct *work) | |||
841 | ret); | 859 | ret); |
842 | } | 860 | } |
843 | 861 | ||
844 | info->mic = true; | ||
845 | info->detecting = false; | ||
846 | goto handled; | 862 | goto handled; |
847 | } | 863 | } |
848 | 864 | ||
@@ -855,10 +871,11 @@ static void arizona_micd_detect(struct work_struct *work) | |||
855 | if (info->detecting && (val & MICD_LVL_1_TO_7)) { | 871 | if (info->detecting && (val & MICD_LVL_1_TO_7)) { |
856 | if (info->jack_flips >= info->micd_num_modes * 10) { | 872 | if (info->jack_flips >= info->micd_num_modes * 10) { |
857 | dev_dbg(arizona->dev, "Detected HP/line\n"); | 873 | dev_dbg(arizona->dev, "Detected HP/line\n"); |
858 | arizona_identify_headphone(info); | ||
859 | 874 | ||
860 | info->detecting = false; | 875 | info->detecting = false; |
861 | 876 | ||
877 | arizona_identify_headphone(info); | ||
878 | |||
862 | arizona_stop_mic(info); | 879 | arizona_stop_mic(info); |
863 | } else { | 880 | } else { |
864 | info->micd_mode++; | 881 | info->micd_mode++; |
@@ -1110,12 +1127,12 @@ static void arizona_micd_set_level(struct arizona *arizona, int index, | |||
1110 | regmap_update_bits(arizona->regmap, reg, mask, level); | 1127 | regmap_update_bits(arizona->regmap, reg, mask, level); |
1111 | } | 1128 | } |
1112 | 1129 | ||
1113 | static int arizona_extcon_of_get_pdata(struct arizona *arizona) | 1130 | static int arizona_extcon_device_get_pdata(struct arizona *arizona) |
1114 | { | 1131 | { |
1115 | struct arizona_pdata *pdata = &arizona->pdata; | 1132 | struct arizona_pdata *pdata = &arizona->pdata; |
1116 | unsigned int val = ARIZONA_ACCDET_MODE_HPL; | 1133 | unsigned int val = ARIZONA_ACCDET_MODE_HPL; |
1117 | 1134 | ||
1118 | of_property_read_u32(arizona->dev->of_node, "wlf,hpdet-channel", &val); | 1135 | device_property_read_u32(arizona->dev, "wlf,hpdet-channel", &val); |
1119 | switch (val) { | 1136 | switch (val) { |
1120 | case ARIZONA_ACCDET_MODE_HPL: | 1137 | case ARIZONA_ACCDET_MODE_HPL: |
1121 | case ARIZONA_ACCDET_MODE_HPR: | 1138 | case ARIZONA_ACCDET_MODE_HPR: |
@@ -1127,6 +1144,24 @@ static int arizona_extcon_of_get_pdata(struct arizona *arizona) | |||
1127 | pdata->hpdet_channel = ARIZONA_ACCDET_MODE_HPL; | 1144 | pdata->hpdet_channel = ARIZONA_ACCDET_MODE_HPL; |
1128 | } | 1145 | } |
1129 | 1146 | ||
1147 | device_property_read_u32(arizona->dev, "wlf,micd-detect-debounce", | ||
1148 | &pdata->micd_detect_debounce); | ||
1149 | |||
1150 | device_property_read_u32(arizona->dev, "wlf,micd-bias-start-time", | ||
1151 | &pdata->micd_bias_start_time); | ||
1152 | |||
1153 | device_property_read_u32(arizona->dev, "wlf,micd-rate", | ||
1154 | &pdata->micd_rate); | ||
1155 | |||
1156 | device_property_read_u32(arizona->dev, "wlf,micd-dbtime", | ||
1157 | &pdata->micd_dbtime); | ||
1158 | |||
1159 | device_property_read_u32(arizona->dev, "wlf,micd-timeout", | ||
1160 | &pdata->micd_timeout); | ||
1161 | |||
1162 | pdata->micd_force_micbias = device_property_read_bool(arizona->dev, | ||
1163 | "wlf,micd-force-micbias"); | ||
1164 | |||
1130 | return 0; | 1165 | return 0; |
1131 | } | 1166 | } |
1132 | 1167 | ||
@@ -1147,10 +1182,8 @@ static int arizona_extcon_probe(struct platform_device *pdev) | |||
1147 | if (!info) | 1182 | if (!info) |
1148 | return -ENOMEM; | 1183 | return -ENOMEM; |
1149 | 1184 | ||
1150 | if (IS_ENABLED(CONFIG_OF)) { | 1185 | if (!dev_get_platdata(arizona->dev)) |
1151 | if (!dev_get_platdata(arizona->dev)) | 1186 | arizona_extcon_device_get_pdata(arizona); |
1152 | arizona_extcon_of_get_pdata(arizona); | ||
1153 | } | ||
1154 | 1187 | ||
1155 | info->micvdd = devm_regulator_get(&pdev->dev, "MICVDD"); | 1188 | info->micvdd = devm_regulator_get(&pdev->dev, "MICVDD"); |
1156 | if (IS_ERR(info->micvdd)) { | 1189 | if (IS_ERR(info->micvdd)) { |
@@ -1241,6 +1274,27 @@ static int arizona_extcon_probe(struct platform_device *pdev) | |||
1241 | arizona->pdata.micd_pol_gpio, ret); | 1274 | arizona->pdata.micd_pol_gpio, ret); |
1242 | goto err_register; | 1275 | goto err_register; |
1243 | } | 1276 | } |
1277 | } else { | ||
1278 | if (info->micd_modes[0].gpio) | ||
1279 | mode = GPIOD_OUT_HIGH; | ||
1280 | else | ||
1281 | mode = GPIOD_OUT_LOW; | ||
1282 | |||
1283 | /* We can't use devm here because we need to do the get | ||
1284 | * against the MFD device, as that is where the of_node | ||
1285 | * will reside, but if we devm against that the GPIO | ||
1286 | * will not be freed if the extcon driver is unloaded. | ||
1287 | */ | ||
1288 | info->micd_pol_gpio = gpiod_get_optional(arizona->dev, | ||
1289 | "wlf,micd-pol", | ||
1290 | GPIOD_OUT_LOW); | ||
1291 | if (IS_ERR(info->micd_pol_gpio)) { | ||
1292 | ret = PTR_ERR(info->micd_pol_gpio); | ||
1293 | dev_err(arizona->dev, | ||
1294 | "Failed to get microphone polarity GPIO: %d\n", | ||
1295 | ret); | ||
1296 | goto err_register; | ||
1297 | } | ||
1244 | } | 1298 | } |
1245 | 1299 | ||
1246 | if (arizona->pdata.hpdet_id_gpio > 0) { | 1300 | if (arizona->pdata.hpdet_id_gpio > 0) { |
@@ -1251,7 +1305,7 @@ static int arizona_extcon_probe(struct platform_device *pdev) | |||
1251 | if (ret != 0) { | 1305 | if (ret != 0) { |
1252 | dev_err(arizona->dev, "Failed to request GPIO%d: %d\n", | 1306 | dev_err(arizona->dev, "Failed to request GPIO%d: %d\n", |
1253 | arizona->pdata.hpdet_id_gpio, ret); | 1307 | arizona->pdata.hpdet_id_gpio, ret); |
1254 | goto err_register; | 1308 | goto err_gpio; |
1255 | } | 1309 | } |
1256 | } | 1310 | } |
1257 | 1311 | ||
@@ -1267,11 +1321,19 @@ static int arizona_extcon_probe(struct platform_device *pdev) | |||
1267 | arizona->pdata.micd_rate | 1321 | arizona->pdata.micd_rate |
1268 | << ARIZONA_MICD_RATE_SHIFT); | 1322 | << ARIZONA_MICD_RATE_SHIFT); |
1269 | 1323 | ||
1270 | if (arizona->pdata.micd_dbtime) | 1324 | switch (arizona->pdata.micd_dbtime) { |
1325 | case MICD_DBTIME_FOUR_READINGS: | ||
1271 | regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1, | 1326 | regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1, |
1272 | ARIZONA_MICD_DBTIME_MASK, | 1327 | ARIZONA_MICD_DBTIME_MASK, |
1273 | arizona->pdata.micd_dbtime | 1328 | ARIZONA_MICD_DBTIME); |
1274 | << ARIZONA_MICD_DBTIME_SHIFT); | 1329 | break; |
1330 | case MICD_DBTIME_TWO_READINGS: | ||
1331 | regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1, | ||
1332 | ARIZONA_MICD_DBTIME_MASK, 0); | ||
1333 | break; | ||
1334 | default: | ||
1335 | break; | ||
1336 | } | ||
1275 | 1337 | ||
1276 | BUILD_BUG_ON(ARRAY_SIZE(arizona_micd_levels) != 0x40); | 1338 | BUILD_BUG_ON(ARRAY_SIZE(arizona_micd_levels) != 0x40); |
1277 | 1339 | ||
@@ -1295,7 +1357,7 @@ static int arizona_extcon_probe(struct platform_device *pdev) | |||
1295 | dev_err(arizona->dev, | 1357 | dev_err(arizona->dev, |
1296 | "MICD ranges must be sorted\n"); | 1358 | "MICD ranges must be sorted\n"); |
1297 | ret = -EINVAL; | 1359 | ret = -EINVAL; |
1298 | goto err_input; | 1360 | goto err_gpio; |
1299 | } | 1361 | } |
1300 | } | 1362 | } |
1301 | } | 1363 | } |
@@ -1314,7 +1376,7 @@ static int arizona_extcon_probe(struct platform_device *pdev) | |||
1314 | dev_err(arizona->dev, "Unsupported MICD level %d\n", | 1376 | dev_err(arizona->dev, "Unsupported MICD level %d\n", |
1315 | info->micd_ranges[i].max); | 1377 | info->micd_ranges[i].max); |
1316 | ret = -EINVAL; | 1378 | ret = -EINVAL; |
1317 | goto err_input; | 1379 | goto err_gpio; |
1318 | } | 1380 | } |
1319 | 1381 | ||
1320 | dev_dbg(arizona->dev, "%d ohms for MICD threshold %d\n", | 1382 | dev_dbg(arizona->dev, "%d ohms for MICD threshold %d\n", |
@@ -1387,7 +1449,7 @@ static int arizona_extcon_probe(struct platform_device *pdev) | |||
1387 | if (ret != 0) { | 1449 | if (ret != 0) { |
1388 | dev_err(&pdev->dev, "Failed to get JACKDET rise IRQ: %d\n", | 1450 | dev_err(&pdev->dev, "Failed to get JACKDET rise IRQ: %d\n", |
1389 | ret); | 1451 | ret); |
1390 | goto err_input; | 1452 | goto err_gpio; |
1391 | } | 1453 | } |
1392 | 1454 | ||
1393 | ret = arizona_set_irq_wake(arizona, jack_irq_rise, 1); | 1455 | ret = arizona_set_irq_wake(arizona, jack_irq_rise, 1); |
@@ -1458,7 +1520,8 @@ err_rise_wake: | |||
1458 | arizona_set_irq_wake(arizona, jack_irq_rise, 0); | 1520 | arizona_set_irq_wake(arizona, jack_irq_rise, 0); |
1459 | err_rise: | 1521 | err_rise: |
1460 | arizona_free_irq(arizona, jack_irq_rise, info); | 1522 | arizona_free_irq(arizona, jack_irq_rise, info); |
1461 | err_input: | 1523 | err_gpio: |
1524 | gpiod_put(info->micd_pol_gpio); | ||
1462 | err_register: | 1525 | err_register: |
1463 | pm_runtime_disable(&pdev->dev); | 1526 | pm_runtime_disable(&pdev->dev); |
1464 | return ret; | 1527 | return ret; |
@@ -1470,6 +1533,8 @@ static int arizona_extcon_remove(struct platform_device *pdev) | |||
1470 | struct arizona *arizona = info->arizona; | 1533 | struct arizona *arizona = info->arizona; |
1471 | int jack_irq_rise, jack_irq_fall; | 1534 | int jack_irq_rise, jack_irq_fall; |
1472 | 1535 | ||
1536 | gpiod_put(info->micd_pol_gpio); | ||
1537 | |||
1473 | pm_runtime_disable(&pdev->dev); | 1538 | pm_runtime_disable(&pdev->dev); |
1474 | 1539 | ||
1475 | regmap_update_bits(arizona->regmap, | 1540 | regmap_update_bits(arizona->regmap, |
diff --git a/drivers/extcon/extcon-gpio.c b/drivers/extcon/extcon-gpio.c index 355459a54e8b..57c24fa52edb 100644 --- a/drivers/extcon/extcon-gpio.c +++ b/drivers/extcon/extcon-gpio.c | |||
@@ -65,22 +65,6 @@ static irqreturn_t gpio_irq_handler(int irq, void *dev_id) | |||
65 | return IRQ_HANDLED; | 65 | return IRQ_HANDLED; |
66 | } | 66 | } |
67 | 67 | ||
68 | static ssize_t extcon_gpio_print_state(struct extcon_dev *edev, char *buf) | ||
69 | { | ||
70 | struct device *dev = edev->dev.parent; | ||
71 | struct gpio_extcon_data *extcon_data = dev_get_drvdata(dev); | ||
72 | const char *state; | ||
73 | |||
74 | if (extcon_get_state(edev)) | ||
75 | state = extcon_data->state_on; | ||
76 | else | ||
77 | state = extcon_data->state_off; | ||
78 | |||
79 | if (state) | ||
80 | return sprintf(buf, "%s\n", state); | ||
81 | return -EINVAL; | ||
82 | } | ||
83 | |||
84 | static int gpio_extcon_probe(struct platform_device *pdev) | 68 | static int gpio_extcon_probe(struct platform_device *pdev) |
85 | { | 69 | { |
86 | struct gpio_extcon_platform_data *pdata = dev_get_platdata(&pdev->dev); | 70 | struct gpio_extcon_platform_data *pdata = dev_get_platdata(&pdev->dev); |
@@ -110,8 +94,6 @@ static int gpio_extcon_probe(struct platform_device *pdev) | |||
110 | extcon_data->state_on = pdata->state_on; | 94 | extcon_data->state_on = pdata->state_on; |
111 | extcon_data->state_off = pdata->state_off; | 95 | extcon_data->state_off = pdata->state_off; |
112 | extcon_data->check_on_resume = pdata->check_on_resume; | 96 | extcon_data->check_on_resume = pdata->check_on_resume; |
113 | if (pdata->state_on && pdata->state_off) | ||
114 | extcon_data->edev->print_state = extcon_gpio_print_state; | ||
115 | 97 | ||
116 | ret = devm_gpio_request_one(&pdev->dev, extcon_data->gpio, GPIOF_DIR_IN, | 98 | ret = devm_gpio_request_one(&pdev->dev, extcon_data->gpio, GPIOF_DIR_IN, |
117 | pdev->name); | 99 | pdev->name); |
diff --git a/drivers/extcon/extcon-max77843.c b/drivers/extcon/extcon-max77843.c index fac2f1417a79..cc5e7bca38c8 100644 --- a/drivers/extcon/extcon-max77843.c +++ b/drivers/extcon/extcon-max77843.c | |||
@@ -781,6 +781,15 @@ static int max77843_muic_probe(struct platform_device *pdev) | |||
781 | /* Support virtual irq domain for max77843 MUIC device */ | 781 | /* Support virtual irq domain for max77843 MUIC device */ |
782 | INIT_WORK(&info->irq_work, max77843_muic_irq_work); | 782 | INIT_WORK(&info->irq_work, max77843_muic_irq_work); |
783 | 783 | ||
784 | /* Clear IRQ bits before request IRQs */ | ||
785 | ret = regmap_bulk_read(max77843->regmap_muic, | ||
786 | MAX77843_MUIC_REG_INT1, info->status, | ||
787 | MAX77843_MUIC_IRQ_NUM); | ||
788 | if (ret) { | ||
789 | dev_err(&pdev->dev, "Failed to Clear IRQ bits\n"); | ||
790 | goto err_muic_irq; | ||
791 | } | ||
792 | |||
784 | for (i = 0; i < ARRAY_SIZE(max77843_muic_irqs); i++) { | 793 | for (i = 0; i < ARRAY_SIZE(max77843_muic_irqs); i++) { |
785 | struct max77843_muic_irq *muic_irq = &max77843_muic_irqs[i]; | 794 | struct max77843_muic_irq *muic_irq = &max77843_muic_irqs[i]; |
786 | unsigned int virq = 0; | 795 | unsigned int virq = 0; |
diff --git a/drivers/extcon/extcon-palmas.c b/drivers/extcon/extcon-palmas.c index eebdf2a33bfe..93c30a885740 100644 --- a/drivers/extcon/extcon-palmas.c +++ b/drivers/extcon/extcon-palmas.c | |||
@@ -28,6 +28,11 @@ | |||
28 | #include <linux/mfd/palmas.h> | 28 | #include <linux/mfd/palmas.h> |
29 | #include <linux/of.h> | 29 | #include <linux/of.h> |
30 | #include <linux/of_platform.h> | 30 | #include <linux/of_platform.h> |
31 | #include <linux/of_gpio.h> | ||
32 | #include <linux/gpio/consumer.h> | ||
33 | #include <linux/workqueue.h> | ||
34 | |||
35 | #define USB_GPIO_DEBOUNCE_MS 20 /* ms */ | ||
31 | 36 | ||
32 | static const unsigned int palmas_extcon_cable[] = { | 37 | static const unsigned int palmas_extcon_cable[] = { |
33 | EXTCON_USB, | 38 | EXTCON_USB, |
@@ -35,8 +40,6 @@ static const unsigned int palmas_extcon_cable[] = { | |||
35 | EXTCON_NONE, | 40 | EXTCON_NONE, |
36 | }; | 41 | }; |
37 | 42 | ||
38 | static const int mutually_exclusive[] = {0x3, 0x0}; | ||
39 | |||
40 | static void palmas_usb_wakeup(struct palmas *palmas, int enable) | 43 | static void palmas_usb_wakeup(struct palmas *palmas, int enable) |
41 | { | 44 | { |
42 | if (enable) | 45 | if (enable) |
@@ -120,19 +123,54 @@ static irqreturn_t palmas_id_irq_handler(int irq, void *_palmas_usb) | |||
120 | return IRQ_HANDLED; | 123 | return IRQ_HANDLED; |
121 | } | 124 | } |
122 | 125 | ||
126 | static void palmas_gpio_id_detect(struct work_struct *work) | ||
127 | { | ||
128 | int id; | ||
129 | struct palmas_usb *palmas_usb = container_of(to_delayed_work(work), | ||
130 | struct palmas_usb, | ||
131 | wq_detectid); | ||
132 | struct extcon_dev *edev = palmas_usb->edev; | ||
133 | |||
134 | if (!palmas_usb->id_gpiod) | ||
135 | return; | ||
136 | |||
137 | id = gpiod_get_value_cansleep(palmas_usb->id_gpiod); | ||
138 | |||
139 | if (id) { | ||
140 | extcon_set_cable_state_(edev, EXTCON_USB_HOST, false); | ||
141 | dev_info(palmas_usb->dev, "USB-HOST cable is detached\n"); | ||
142 | } else { | ||
143 | extcon_set_cable_state_(edev, EXTCON_USB_HOST, true); | ||
144 | dev_info(palmas_usb->dev, "USB-HOST cable is attached\n"); | ||
145 | } | ||
146 | } | ||
147 | |||
148 | static irqreturn_t palmas_gpio_id_irq_handler(int irq, void *_palmas_usb) | ||
149 | { | ||
150 | struct palmas_usb *palmas_usb = _palmas_usb; | ||
151 | |||
152 | queue_delayed_work(system_power_efficient_wq, &palmas_usb->wq_detectid, | ||
153 | palmas_usb->sw_debounce_jiffies); | ||
154 | |||
155 | return IRQ_HANDLED; | ||
156 | } | ||
157 | |||
123 | static void palmas_enable_irq(struct palmas_usb *palmas_usb) | 158 | static void palmas_enable_irq(struct palmas_usb *palmas_usb) |
124 | { | 159 | { |
125 | palmas_write(palmas_usb->palmas, PALMAS_USB_OTG_BASE, | 160 | palmas_write(palmas_usb->palmas, PALMAS_USB_OTG_BASE, |
126 | PALMAS_USB_VBUS_CTRL_SET, | 161 | PALMAS_USB_VBUS_CTRL_SET, |
127 | PALMAS_USB_VBUS_CTRL_SET_VBUS_ACT_COMP); | 162 | PALMAS_USB_VBUS_CTRL_SET_VBUS_ACT_COMP); |
128 | 163 | ||
129 | palmas_write(palmas_usb->palmas, PALMAS_USB_OTG_BASE, | 164 | if (palmas_usb->enable_id_detection) { |
130 | PALMAS_USB_ID_CTRL_SET, PALMAS_USB_ID_CTRL_SET_ID_ACT_COMP); | 165 | palmas_write(palmas_usb->palmas, PALMAS_USB_OTG_BASE, |
166 | PALMAS_USB_ID_CTRL_SET, | ||
167 | PALMAS_USB_ID_CTRL_SET_ID_ACT_COMP); | ||
131 | 168 | ||
132 | palmas_write(palmas_usb->palmas, PALMAS_USB_OTG_BASE, | 169 | palmas_write(palmas_usb->palmas, PALMAS_USB_OTG_BASE, |
133 | PALMAS_USB_ID_INT_EN_HI_SET, | 170 | PALMAS_USB_ID_INT_EN_HI_SET, |
134 | PALMAS_USB_ID_INT_EN_HI_SET_ID_GND | | 171 | PALMAS_USB_ID_INT_EN_HI_SET_ID_GND | |
135 | PALMAS_USB_ID_INT_EN_HI_SET_ID_FLOAT); | 172 | PALMAS_USB_ID_INT_EN_HI_SET_ID_FLOAT); |
173 | } | ||
136 | 174 | ||
137 | if (palmas_usb->enable_vbus_detection) | 175 | if (palmas_usb->enable_vbus_detection) |
138 | palmas_vbus_irq_handler(palmas_usb->vbus_irq, palmas_usb); | 176 | palmas_vbus_irq_handler(palmas_usb->vbus_irq, palmas_usb); |
@@ -171,20 +209,37 @@ static int palmas_usb_probe(struct platform_device *pdev) | |||
171 | palmas_usb->wakeup = pdata->wakeup; | 209 | palmas_usb->wakeup = pdata->wakeup; |
172 | } | 210 | } |
173 | 211 | ||
212 | palmas_usb->id_gpiod = devm_gpiod_get_optional(&pdev->dev, "id", | ||
213 | GPIOD_IN); | ||
214 | if (IS_ERR(palmas_usb->id_gpiod)) { | ||
215 | dev_err(&pdev->dev, "failed to get id gpio\n"); | ||
216 | return PTR_ERR(palmas_usb->id_gpiod); | ||
217 | } | ||
218 | |||
219 | if (palmas_usb->enable_id_detection && palmas_usb->id_gpiod) { | ||
220 | palmas_usb->enable_id_detection = false; | ||
221 | palmas_usb->enable_gpio_id_detection = true; | ||
222 | } | ||
223 | |||
224 | if (palmas_usb->enable_gpio_id_detection) { | ||
225 | u32 debounce; | ||
226 | |||
227 | if (of_property_read_u32(node, "debounce-delay-ms", &debounce)) | ||
228 | debounce = USB_GPIO_DEBOUNCE_MS; | ||
229 | |||
230 | status = gpiod_set_debounce(palmas_usb->id_gpiod, | ||
231 | debounce * 1000); | ||
232 | if (status < 0) | ||
233 | palmas_usb->sw_debounce_jiffies = msecs_to_jiffies(debounce); | ||
234 | } | ||
235 | |||
236 | INIT_DELAYED_WORK(&palmas_usb->wq_detectid, palmas_gpio_id_detect); | ||
237 | |||
174 | palmas->usb = palmas_usb; | 238 | palmas->usb = palmas_usb; |
175 | palmas_usb->palmas = palmas; | 239 | palmas_usb->palmas = palmas; |
176 | 240 | ||
177 | palmas_usb->dev = &pdev->dev; | 241 | palmas_usb->dev = &pdev->dev; |
178 | 242 | ||
179 | palmas_usb->id_otg_irq = regmap_irq_get_virq(palmas->irq_data, | ||
180 | PALMAS_ID_OTG_IRQ); | ||
181 | palmas_usb->id_irq = regmap_irq_get_virq(palmas->irq_data, | ||
182 | PALMAS_ID_IRQ); | ||
183 | palmas_usb->vbus_otg_irq = regmap_irq_get_virq(palmas->irq_data, | ||
184 | PALMAS_VBUS_OTG_IRQ); | ||
185 | palmas_usb->vbus_irq = regmap_irq_get_virq(palmas->irq_data, | ||
186 | PALMAS_VBUS_IRQ); | ||
187 | |||
188 | palmas_usb_wakeup(palmas, palmas_usb->wakeup); | 243 | palmas_usb_wakeup(palmas, palmas_usb->wakeup); |
189 | 244 | ||
190 | platform_set_drvdata(pdev, palmas_usb); | 245 | platform_set_drvdata(pdev, palmas_usb); |
@@ -195,7 +250,6 @@ static int palmas_usb_probe(struct platform_device *pdev) | |||
195 | dev_err(&pdev->dev, "failed to allocate extcon device\n"); | 250 | dev_err(&pdev->dev, "failed to allocate extcon device\n"); |
196 | return -ENOMEM; | 251 | return -ENOMEM; |
197 | } | 252 | } |
198 | palmas_usb->edev->mutually_exclusive = mutually_exclusive; | ||
199 | 253 | ||
200 | status = devm_extcon_dev_register(&pdev->dev, palmas_usb->edev); | 254 | status = devm_extcon_dev_register(&pdev->dev, palmas_usb->edev); |
201 | if (status) { | 255 | if (status) { |
@@ -204,6 +258,10 @@ static int palmas_usb_probe(struct platform_device *pdev) | |||
204 | } | 258 | } |
205 | 259 | ||
206 | if (palmas_usb->enable_id_detection) { | 260 | if (palmas_usb->enable_id_detection) { |
261 | palmas_usb->id_otg_irq = regmap_irq_get_virq(palmas->irq_data, | ||
262 | PALMAS_ID_OTG_IRQ); | ||
263 | palmas_usb->id_irq = regmap_irq_get_virq(palmas->irq_data, | ||
264 | PALMAS_ID_IRQ); | ||
207 | status = devm_request_threaded_irq(palmas_usb->dev, | 265 | status = devm_request_threaded_irq(palmas_usb->dev, |
208 | palmas_usb->id_irq, | 266 | palmas_usb->id_irq, |
209 | NULL, palmas_id_irq_handler, | 267 | NULL, palmas_id_irq_handler, |
@@ -215,9 +273,33 @@ static int palmas_usb_probe(struct platform_device *pdev) | |||
215 | palmas_usb->id_irq, status); | 273 | palmas_usb->id_irq, status); |
216 | return status; | 274 | return status; |
217 | } | 275 | } |
276 | } else if (palmas_usb->enable_gpio_id_detection) { | ||
277 | palmas_usb->gpio_id_irq = gpiod_to_irq(palmas_usb->id_gpiod); | ||
278 | if (palmas_usb->gpio_id_irq < 0) { | ||
279 | dev_err(&pdev->dev, "failed to get id irq\n"); | ||
280 | return palmas_usb->gpio_id_irq; | ||
281 | } | ||
282 | status = devm_request_threaded_irq(&pdev->dev, | ||
283 | palmas_usb->gpio_id_irq, | ||
284 | NULL, | ||
285 | palmas_gpio_id_irq_handler, | ||
286 | IRQF_TRIGGER_RISING | | ||
287 | IRQF_TRIGGER_FALLING | | ||
288 | IRQF_ONESHOT, | ||
289 | "palmas_usb_id", | ||
290 | palmas_usb); | ||
291 | if (status < 0) { | ||
292 | dev_err(&pdev->dev, | ||
293 | "failed to request handler for id irq\n"); | ||
294 | return status; | ||
295 | } | ||
218 | } | 296 | } |
219 | 297 | ||
220 | if (palmas_usb->enable_vbus_detection) { | 298 | if (palmas_usb->enable_vbus_detection) { |
299 | palmas_usb->vbus_otg_irq = regmap_irq_get_virq(palmas->irq_data, | ||
300 | PALMAS_VBUS_OTG_IRQ); | ||
301 | palmas_usb->vbus_irq = regmap_irq_get_virq(palmas->irq_data, | ||
302 | PALMAS_VBUS_IRQ); | ||
221 | status = devm_request_threaded_irq(palmas_usb->dev, | 303 | status = devm_request_threaded_irq(palmas_usb->dev, |
222 | palmas_usb->vbus_irq, NULL, | 304 | palmas_usb->vbus_irq, NULL, |
223 | palmas_vbus_irq_handler, | 305 | palmas_vbus_irq_handler, |
@@ -232,10 +314,21 @@ static int palmas_usb_probe(struct platform_device *pdev) | |||
232 | } | 314 | } |
233 | 315 | ||
234 | palmas_enable_irq(palmas_usb); | 316 | palmas_enable_irq(palmas_usb); |
317 | /* perform initial detection */ | ||
318 | palmas_gpio_id_detect(&palmas_usb->wq_detectid.work); | ||
235 | device_set_wakeup_capable(&pdev->dev, true); | 319 | device_set_wakeup_capable(&pdev->dev, true); |
236 | return 0; | 320 | return 0; |
237 | } | 321 | } |
238 | 322 | ||
323 | static int palmas_usb_remove(struct platform_device *pdev) | ||
324 | { | ||
325 | struct palmas_usb *palmas_usb = platform_get_drvdata(pdev); | ||
326 | |||
327 | cancel_delayed_work_sync(&palmas_usb->wq_detectid); | ||
328 | |||
329 | return 0; | ||
330 | } | ||
331 | |||
239 | #ifdef CONFIG_PM_SLEEP | 332 | #ifdef CONFIG_PM_SLEEP |
240 | static int palmas_usb_suspend(struct device *dev) | 333 | static int palmas_usb_suspend(struct device *dev) |
241 | { | 334 | { |
@@ -246,6 +339,8 @@ static int palmas_usb_suspend(struct device *dev) | |||
246 | enable_irq_wake(palmas_usb->vbus_irq); | 339 | enable_irq_wake(palmas_usb->vbus_irq); |
247 | if (palmas_usb->enable_id_detection) | 340 | if (palmas_usb->enable_id_detection) |
248 | enable_irq_wake(palmas_usb->id_irq); | 341 | enable_irq_wake(palmas_usb->id_irq); |
342 | if (palmas_usb->enable_gpio_id_detection) | ||
343 | enable_irq_wake(palmas_usb->gpio_id_irq); | ||
249 | } | 344 | } |
250 | return 0; | 345 | return 0; |
251 | } | 346 | } |
@@ -259,6 +354,8 @@ static int palmas_usb_resume(struct device *dev) | |||
259 | disable_irq_wake(palmas_usb->vbus_irq); | 354 | disable_irq_wake(palmas_usb->vbus_irq); |
260 | if (palmas_usb->enable_id_detection) | 355 | if (palmas_usb->enable_id_detection) |
261 | disable_irq_wake(palmas_usb->id_irq); | 356 | disable_irq_wake(palmas_usb->id_irq); |
357 | if (palmas_usb->enable_gpio_id_detection) | ||
358 | disable_irq_wake(palmas_usb->gpio_id_irq); | ||
262 | } | 359 | } |
263 | return 0; | 360 | return 0; |
264 | }; | 361 | }; |
@@ -276,6 +373,7 @@ static const struct of_device_id of_palmas_match_tbl[] = { | |||
276 | 373 | ||
277 | static struct platform_driver palmas_usb_driver = { | 374 | static struct platform_driver palmas_usb_driver = { |
278 | .probe = palmas_usb_probe, | 375 | .probe = palmas_usb_probe, |
376 | .remove = palmas_usb_remove, | ||
279 | .driver = { | 377 | .driver = { |
280 | .name = "palmas-usb", | 378 | .name = "palmas-usb", |
281 | .of_match_table = of_palmas_match_tbl, | 379 | .of_match_table = of_palmas_match_tbl, |
diff --git a/drivers/extcon/extcon-rt8973a.c b/drivers/extcon/extcon-rt8973a.c index 92c939221a41..11592e980bc1 100644 --- a/drivers/extcon/extcon-rt8973a.c +++ b/drivers/extcon/extcon-rt8973a.c | |||
@@ -693,7 +693,6 @@ MODULE_DEVICE_TABLE(i2c, rt8973a_i2c_id); | |||
693 | static struct i2c_driver rt8973a_muic_i2c_driver = { | 693 | static struct i2c_driver rt8973a_muic_i2c_driver = { |
694 | .driver = { | 694 | .driver = { |
695 | .name = "rt8973a", | 695 | .name = "rt8973a", |
696 | .owner = THIS_MODULE, | ||
697 | .pm = &rt8973a_muic_pm_ops, | 696 | .pm = &rt8973a_muic_pm_ops, |
698 | .of_match_table = rt8973a_dt_match, | 697 | .of_match_table = rt8973a_dt_match, |
699 | }, | 698 | }, |
diff --git a/drivers/extcon/extcon-sm5502.c b/drivers/extcon/extcon-sm5502.c index 817dece23b4c..0ffefefa2e26 100644 --- a/drivers/extcon/extcon-sm5502.c +++ b/drivers/extcon/extcon-sm5502.c | |||
@@ -685,7 +685,6 @@ MODULE_DEVICE_TABLE(i2c, sm5502_i2c_id); | |||
685 | static struct i2c_driver sm5502_muic_i2c_driver = { | 685 | static struct i2c_driver sm5502_muic_i2c_driver = { |
686 | .driver = { | 686 | .driver = { |
687 | .name = "sm5502", | 687 | .name = "sm5502", |
688 | .owner = THIS_MODULE, | ||
689 | .pm = &sm5502_muic_pm_ops, | 688 | .pm = &sm5502_muic_pm_ops, |
690 | .of_match_table = sm5502_dt_match, | 689 | .of_match_table = sm5502_dt_match, |
691 | }, | 690 | }, |
diff --git a/drivers/extcon/extcon-usb-gpio.c b/drivers/extcon/extcon-usb-gpio.c index a2a44536a608..2b2fecffb1ad 100644 --- a/drivers/extcon/extcon-usb-gpio.c +++ b/drivers/extcon/extcon-usb-gpio.c | |||
@@ -15,6 +15,7 @@ | |||
15 | */ | 15 | */ |
16 | 16 | ||
17 | #include <linux/extcon.h> | 17 | #include <linux/extcon.h> |
18 | #include <linux/gpio.h> | ||
18 | #include <linux/gpio/consumer.h> | 19 | #include <linux/gpio/consumer.h> |
19 | #include <linux/init.h> | 20 | #include <linux/init.h> |
20 | #include <linux/interrupt.h> | 21 | #include <linux/interrupt.h> |
diff --git a/drivers/extcon/extcon.c b/drivers/extcon/extcon.c index 43b57b02d050..a07addde297b 100644 --- a/drivers/extcon/extcon.c +++ b/drivers/extcon/extcon.c | |||
@@ -126,7 +126,7 @@ static int find_cable_index_by_id(struct extcon_dev *edev, const unsigned int id | |||
126 | 126 | ||
127 | static int find_cable_id_by_name(struct extcon_dev *edev, const char *name) | 127 | static int find_cable_id_by_name(struct extcon_dev *edev, const char *name) |
128 | { | 128 | { |
129 | unsigned int id = -EINVAL; | 129 | int id = -EINVAL; |
130 | int i = 0; | 130 | int i = 0; |
131 | 131 | ||
132 | /* Find the id of extcon cable */ | 132 | /* Find the id of extcon cable */ |
@@ -143,7 +143,7 @@ static int find_cable_id_by_name(struct extcon_dev *edev, const char *name) | |||
143 | 143 | ||
144 | static int find_cable_index_by_name(struct extcon_dev *edev, const char *name) | 144 | static int find_cable_index_by_name(struct extcon_dev *edev, const char *name) |
145 | { | 145 | { |
146 | unsigned int id; | 146 | int id; |
147 | 147 | ||
148 | if (edev->max_supported == 0) | 148 | if (edev->max_supported == 0) |
149 | return -EINVAL; | 149 | return -EINVAL; |
@@ -172,14 +172,6 @@ static ssize_t state_show(struct device *dev, struct device_attribute *attr, | |||
172 | int i, count = 0; | 172 | int i, count = 0; |
173 | struct extcon_dev *edev = dev_get_drvdata(dev); | 173 | struct extcon_dev *edev = dev_get_drvdata(dev); |
174 | 174 | ||
175 | if (edev->print_state) { | ||
176 | int ret = edev->print_state(edev, buf); | ||
177 | |||
178 | if (ret >= 0) | ||
179 | return ret; | ||
180 | /* Use default if failed */ | ||
181 | } | ||
182 | |||
183 | if (edev->max_supported == 0) | 175 | if (edev->max_supported == 0) |
184 | return sprintf(buf, "%u\n", edev->state); | 176 | return sprintf(buf, "%u\n", edev->state); |
185 | 177 | ||
@@ -272,6 +264,9 @@ int extcon_update_state(struct extcon_dev *edev, u32 mask, u32 state) | |||
272 | unsigned long flags; | 264 | unsigned long flags; |
273 | bool attached; | 265 | bool attached; |
274 | 266 | ||
267 | if (!edev) | ||
268 | return -EINVAL; | ||
269 | |||
275 | spin_lock_irqsave(&edev->lock, flags); | 270 | spin_lock_irqsave(&edev->lock, flags); |
276 | 271 | ||
277 | if (edev->state != ((edev->state & ~mask) | (state & mask))) { | 272 | if (edev->state != ((edev->state & ~mask) | (state & mask))) { |
@@ -345,6 +340,9 @@ EXPORT_SYMBOL_GPL(extcon_update_state); | |||
345 | */ | 340 | */ |
346 | int extcon_set_state(struct extcon_dev *edev, u32 state) | 341 | int extcon_set_state(struct extcon_dev *edev, u32 state) |
347 | { | 342 | { |
343 | if (!edev) | ||
344 | return -EINVAL; | ||
345 | |||
348 | return extcon_update_state(edev, 0xffffffff, state); | 346 | return extcon_update_state(edev, 0xffffffff, state); |
349 | } | 347 | } |
350 | EXPORT_SYMBOL_GPL(extcon_set_state); | 348 | EXPORT_SYMBOL_GPL(extcon_set_state); |
@@ -358,6 +356,9 @@ int extcon_get_cable_state_(struct extcon_dev *edev, const unsigned int id) | |||
358 | { | 356 | { |
359 | int index; | 357 | int index; |
360 | 358 | ||
359 | if (!edev) | ||
360 | return -EINVAL; | ||
361 | |||
361 | index = find_cable_index_by_id(edev, id); | 362 | index = find_cable_index_by_id(edev, id); |
362 | if (index < 0) | 363 | if (index < 0) |
363 | return index; | 364 | return index; |
@@ -378,7 +379,7 @@ EXPORT_SYMBOL_GPL(extcon_get_cable_state_); | |||
378 | */ | 379 | */ |
379 | int extcon_get_cable_state(struct extcon_dev *edev, const char *cable_name) | 380 | int extcon_get_cable_state(struct extcon_dev *edev, const char *cable_name) |
380 | { | 381 | { |
381 | unsigned int id; | 382 | int id; |
382 | 383 | ||
383 | id = find_cable_id_by_name(edev, cable_name); | 384 | id = find_cable_id_by_name(edev, cable_name); |
384 | if (id < 0) | 385 | if (id < 0) |
@@ -402,6 +403,9 @@ int extcon_set_cable_state_(struct extcon_dev *edev, unsigned int id, | |||
402 | u32 state; | 403 | u32 state; |
403 | int index; | 404 | int index; |
404 | 405 | ||
406 | if (!edev) | ||
407 | return -EINVAL; | ||
408 | |||
405 | index = find_cable_index_by_id(edev, id); | 409 | index = find_cable_index_by_id(edev, id); |
406 | if (index < 0) | 410 | if (index < 0) |
407 | return index; | 411 | return index; |
@@ -426,7 +430,7 @@ EXPORT_SYMBOL_GPL(extcon_set_cable_state_); | |||
426 | int extcon_set_cable_state(struct extcon_dev *edev, | 430 | int extcon_set_cable_state(struct extcon_dev *edev, |
427 | const char *cable_name, bool cable_state) | 431 | const char *cable_name, bool cable_state) |
428 | { | 432 | { |
429 | unsigned int id; | 433 | int id; |
430 | 434 | ||
431 | id = find_cable_id_by_name(edev, cable_name); | 435 | id = find_cable_id_by_name(edev, cable_name); |
432 | if (id < 0) | 436 | if (id < 0) |
@@ -444,6 +448,9 @@ struct extcon_dev *extcon_get_extcon_dev(const char *extcon_name) | |||
444 | { | 448 | { |
445 | struct extcon_dev *sd; | 449 | struct extcon_dev *sd; |
446 | 450 | ||
451 | if (!extcon_name) | ||
452 | return ERR_PTR(-EINVAL); | ||
453 | |||
447 | mutex_lock(&extcon_dev_list_lock); | 454 | mutex_lock(&extcon_dev_list_lock); |
448 | list_for_each_entry(sd, &extcon_dev_list, entry) { | 455 | list_for_each_entry(sd, &extcon_dev_list, entry) { |
449 | if (!strcmp(sd->name, extcon_name)) | 456 | if (!strcmp(sd->name, extcon_name)) |
@@ -572,6 +579,9 @@ int extcon_register_notifier(struct extcon_dev *edev, unsigned int id, | |||
572 | unsigned long flags; | 579 | unsigned long flags; |
573 | int ret, idx; | 580 | int ret, idx; |
574 | 581 | ||
582 | if (!edev || !nb) | ||
583 | return -EINVAL; | ||
584 | |||
575 | idx = find_cable_index_by_id(edev, id); | 585 | idx = find_cable_index_by_id(edev, id); |
576 | 586 | ||
577 | spin_lock_irqsave(&edev->lock, flags); | 587 | spin_lock_irqsave(&edev->lock, flags); |
@@ -594,6 +604,9 @@ int extcon_unregister_notifier(struct extcon_dev *edev, unsigned int id, | |||
594 | unsigned long flags; | 604 | unsigned long flags; |
595 | int ret, idx; | 605 | int ret, idx; |
596 | 606 | ||
607 | if (!edev || !nb) | ||
608 | return -EINVAL; | ||
609 | |||
597 | idx = find_cable_index_by_id(edev, id); | 610 | idx = find_cable_index_by_id(edev, id); |
598 | 611 | ||
599 | spin_lock_irqsave(&edev->lock, flags); | 612 | spin_lock_irqsave(&edev->lock, flags); |
@@ -654,6 +667,9 @@ struct extcon_dev *extcon_dev_allocate(const unsigned int *supported_cable) | |||
654 | { | 667 | { |
655 | struct extcon_dev *edev; | 668 | struct extcon_dev *edev; |
656 | 669 | ||
670 | if (!supported_cable) | ||
671 | return ERR_PTR(-EINVAL); | ||
672 | |||
657 | edev = kzalloc(sizeof(*edev), GFP_KERNEL); | 673 | edev = kzalloc(sizeof(*edev), GFP_KERNEL); |
658 | if (!edev) | 674 | if (!edev) |
659 | return ERR_PTR(-ENOMEM); | 675 | return ERR_PTR(-ENOMEM); |
@@ -754,7 +770,7 @@ int extcon_dev_register(struct extcon_dev *edev) | |||
754 | return ret; | 770 | return ret; |
755 | } | 771 | } |
756 | 772 | ||
757 | if (!edev->supported_cable) | 773 | if (!edev || !edev->supported_cable) |
758 | return -EINVAL; | 774 | return -EINVAL; |
759 | 775 | ||
760 | for (; edev->supported_cable[index] != EXTCON_NONE; index++); | 776 | for (; edev->supported_cable[index] != EXTCON_NONE; index++); |
@@ -960,6 +976,9 @@ void extcon_dev_unregister(struct extcon_dev *edev) | |||
960 | { | 976 | { |
961 | int index; | 977 | int index; |
962 | 978 | ||
979 | if (!edev) | ||
980 | return; | ||
981 | |||
963 | mutex_lock(&extcon_dev_list_lock); | 982 | mutex_lock(&extcon_dev_list_lock); |
964 | list_del(&edev->entry); | 983 | list_del(&edev->entry); |
965 | mutex_unlock(&extcon_dev_list_lock); | 984 | mutex_unlock(&extcon_dev_list_lock); |
@@ -1066,6 +1085,9 @@ struct extcon_dev *extcon_get_edev_by_phandle(struct device *dev, int index) | |||
1066 | struct device_node *node; | 1085 | struct device_node *node; |
1067 | struct extcon_dev *edev; | 1086 | struct extcon_dev *edev; |
1068 | 1087 | ||
1088 | if (!dev) | ||
1089 | return ERR_PTR(-EINVAL); | ||
1090 | |||
1069 | if (!dev->of_node) { | 1091 | if (!dev->of_node) { |
1070 | dev_err(dev, "device does not have a device node entry\n"); | 1092 | dev_err(dev, "device does not have a device node entry\n"); |
1071 | return ERR_PTR(-EINVAL); | 1093 | return ERR_PTR(-EINVAL); |
diff --git a/include/linux/extcon.h b/include/linux/extcon.h index b16d929fa75f..c0f8c4fc5d45 100644 --- a/include/linux/extcon.h +++ b/include/linux/extcon.h | |||
@@ -27,8 +27,6 @@ | |||
27 | #define __LINUX_EXTCON_H__ | 27 | #define __LINUX_EXTCON_H__ |
28 | 28 | ||
29 | #include <linux/device.h> | 29 | #include <linux/device.h> |
30 | #include <linux/notifier.h> | ||
31 | #include <linux/sysfs.h> | ||
32 | 30 | ||
33 | /* | 31 | /* |
34 | * Define the unique id of supported external connectors | 32 | * Define the unique id of supported external connectors |
@@ -77,8 +75,6 @@ struct extcon_cable; | |||
77 | * be attached simulataneously. {0x7, 0} is equivalent to | 75 | * be attached simulataneously. {0x7, 0} is equivalent to |
78 | * {0x3, 0x6, 0x5, 0}. If it is {0xFFFFFFFF, 0}, there | 76 | * {0x3, 0x6, 0x5, 0}. If it is {0xFFFFFFFF, 0}, there |
79 | * can be no simultaneous connections. | 77 | * can be no simultaneous connections. |
80 | * @print_state: An optional callback to override the method to print the | ||
81 | * status of the extcon device. | ||
82 | * @dev: Device of this extcon. | 78 | * @dev: Device of this extcon. |
83 | * @state: Attach/detach state of this extcon. Do not provide at | 79 | * @state: Attach/detach state of this extcon. Do not provide at |
84 | * register-time. | 80 | * register-time. |
@@ -102,9 +98,6 @@ struct extcon_dev { | |||
102 | const unsigned int *supported_cable; | 98 | const unsigned int *supported_cable; |
103 | const u32 *mutually_exclusive; | 99 | const u32 *mutually_exclusive; |
104 | 100 | ||
105 | /* Optional callbacks to override class functions */ | ||
106 | ssize_t (*print_state)(struct extcon_dev *edev, char *buf); | ||
107 | |||
108 | /* Internal data. Please do not set. */ | 101 | /* Internal data. Please do not set. */ |
109 | struct device dev; | 102 | struct device dev; |
110 | struct raw_notifier_head *nh; | 103 | struct raw_notifier_head *nh; |
diff --git a/include/linux/mfd/palmas.h b/include/linux/mfd/palmas.h index bb270bd03eed..13e1d96935ed 100644 --- a/include/linux/mfd/palmas.h +++ b/include/linux/mfd/palmas.h | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/regmap.h> | 21 | #include <linux/regmap.h> |
22 | #include <linux/regulator/driver.h> | 22 | #include <linux/regulator/driver.h> |
23 | #include <linux/extcon.h> | 23 | #include <linux/extcon.h> |
24 | #include <linux/of_gpio.h> | ||
24 | #include <linux/usb/phy_companion.h> | 25 | #include <linux/usb/phy_companion.h> |
25 | 26 | ||
26 | #define PALMAS_NUM_CLIENTS 3 | 27 | #define PALMAS_NUM_CLIENTS 3 |
@@ -551,10 +552,16 @@ struct palmas_usb { | |||
551 | int vbus_otg_irq; | 552 | int vbus_otg_irq; |
552 | int vbus_irq; | 553 | int vbus_irq; |
553 | 554 | ||
555 | int gpio_id_irq; | ||
556 | struct gpio_desc *id_gpiod; | ||
557 | unsigned long sw_debounce_jiffies; | ||
558 | struct delayed_work wq_detectid; | ||
559 | |||
554 | enum palmas_usb_state linkstat; | 560 | enum palmas_usb_state linkstat; |
555 | int wakeup; | 561 | int wakeup; |
556 | bool enable_vbus_detection; | 562 | bool enable_vbus_detection; |
557 | bool enable_id_detection; | 563 | bool enable_id_detection; |
564 | bool enable_gpio_id_detection; | ||
558 | }; | 565 | }; |
559 | 566 | ||
560 | #define comparator_to_palmas(x) container_of((x), struct palmas_usb, comparator) | 567 | #define comparator_to_palmas(x) container_of((x), struct palmas_usb, comparator) |