diff options
Diffstat (limited to 'drivers/extcon')
| -rw-r--r-- | drivers/extcon/Kconfig | 4 | ||||
| -rw-r--r-- | drivers/extcon/extcon-adc-jack.c | 49 | ||||
| -rw-r--r-- | drivers/extcon/extcon-arizona.c | 40 | ||||
| -rw-r--r-- | drivers/extcon/extcon-class.c | 151 | ||||
| -rw-r--r-- | drivers/extcon/extcon-gpio.c | 37 | ||||
| -rw-r--r-- | drivers/extcon/extcon-max14577.c | 199 | ||||
| -rw-r--r-- | drivers/extcon/extcon-max77693.c | 23 | ||||
| -rw-r--r-- | drivers/extcon/extcon-max8997.c | 16 | ||||
| -rw-r--r-- | drivers/extcon/extcon-palmas.c | 41 |
9 files changed, 386 insertions, 174 deletions
diff --git a/drivers/extcon/Kconfig b/drivers/extcon/Kconfig index be56e8ac95e6..aebde489c291 100644 --- a/drivers/extcon/Kconfig +++ b/drivers/extcon/Kconfig | |||
| @@ -28,13 +28,13 @@ config EXTCON_ADC_JACK | |||
| 28 | Say Y here to enable extcon device driver based on ADC values. | 28 | Say Y here to enable extcon device driver based on ADC values. |
| 29 | 29 | ||
| 30 | config EXTCON_MAX14577 | 30 | config EXTCON_MAX14577 |
| 31 | tristate "MAX14577 EXTCON Support" | 31 | tristate "MAX14577/77836 EXTCON Support" |
| 32 | depends on MFD_MAX14577 | 32 | depends on MFD_MAX14577 |
| 33 | select IRQ_DOMAIN | 33 | select IRQ_DOMAIN |
| 34 | select REGMAP_I2C | 34 | select REGMAP_I2C |
| 35 | help | 35 | help |
| 36 | If you say yes here you get support for the MUIC device of | 36 | If you say yes here you get support for the MUIC device of |
| 37 | Maxim MAX14577 PMIC. The MAX14577 MUIC is a USB port accessory | 37 | Maxim MAX14577/77836. The MAX14577/77836 MUIC is a USB port accessory |
| 38 | detector and switch. | 38 | detector and switch. |
| 39 | 39 | ||
| 40 | config EXTCON_MAX77693 | 40 | config EXTCON_MAX77693 |
diff --git a/drivers/extcon/extcon-adc-jack.c b/drivers/extcon/extcon-adc-jack.c index e23f1c2e5053..e18f95be3733 100644 --- a/drivers/extcon/extcon-adc-jack.c +++ b/drivers/extcon/extcon-adc-jack.c | |||
| @@ -39,7 +39,7 @@ | |||
| 39 | * @chan: iio channel being queried. | 39 | * @chan: iio channel being queried. |
| 40 | */ | 40 | */ |
| 41 | struct adc_jack_data { | 41 | struct adc_jack_data { |
| 42 | struct extcon_dev edev; | 42 | struct extcon_dev *edev; |
| 43 | 43 | ||
| 44 | const char **cable_names; | 44 | const char **cable_names; |
| 45 | int num_cables; | 45 | int num_cables; |
| @@ -64,7 +64,7 @@ static void adc_jack_handler(struct work_struct *work) | |||
| 64 | 64 | ||
| 65 | ret = iio_read_channel_raw(data->chan, &adc_val); | 65 | ret = iio_read_channel_raw(data->chan, &adc_val); |
| 66 | if (ret < 0) { | 66 | if (ret < 0) { |
| 67 | dev_err(&data->edev.dev, "read channel() error: %d\n", ret); | 67 | dev_err(&data->edev->dev, "read channel() error: %d\n", ret); |
| 68 | return; | 68 | return; |
| 69 | } | 69 | } |
| 70 | 70 | ||
| @@ -80,7 +80,7 @@ static void adc_jack_handler(struct work_struct *work) | |||
| 80 | } | 80 | } |
| 81 | /* if no def has met, it means state = 0 (no cables attached) */ | 81 | /* if no def has met, it means state = 0 (no cables attached) */ |
| 82 | 82 | ||
| 83 | extcon_set_state(&data->edev, state); | 83 | extcon_set_state(data->edev, state); |
| 84 | } | 84 | } |
| 85 | 85 | ||
| 86 | static irqreturn_t adc_jack_irq_thread(int irq, void *_data) | 86 | static irqreturn_t adc_jack_irq_thread(int irq, void *_data) |
| @@ -102,33 +102,33 @@ static int adc_jack_probe(struct platform_device *pdev) | |||
| 102 | if (!data) | 102 | if (!data) |
| 103 | return -ENOMEM; | 103 | return -ENOMEM; |
| 104 | 104 | ||
| 105 | data->edev.name = pdata->name; | ||
| 106 | |||
| 107 | if (!pdata->cable_names) { | 105 | if (!pdata->cable_names) { |
| 108 | err = -EINVAL; | ||
| 109 | dev_err(&pdev->dev, "error: cable_names not defined.\n"); | 106 | dev_err(&pdev->dev, "error: cable_names not defined.\n"); |
| 110 | goto out; | 107 | return -EINVAL; |
| 111 | } | 108 | } |
| 112 | 109 | ||
| 113 | data->edev.dev.parent = &pdev->dev; | 110 | data->edev = devm_extcon_dev_allocate(&pdev->dev, pdata->cable_names); |
| 114 | data->edev.supported_cable = pdata->cable_names; | 111 | if (IS_ERR(data->edev)) { |
| 112 | dev_err(&pdev->dev, "failed to allocate extcon device\n"); | ||
| 113 | return -ENOMEM; | ||
| 114 | } | ||
| 115 | data->edev->dev.parent = &pdev->dev; | ||
| 116 | data->edev->name = pdata->name; | ||
| 115 | 117 | ||
| 116 | /* Check the length of array and set num_cables */ | 118 | /* Check the length of array and set num_cables */ |
| 117 | for (i = 0; data->edev.supported_cable[i]; i++) | 119 | for (i = 0; data->edev->supported_cable[i]; i++) |
| 118 | ; | 120 | ; |
| 119 | if (i == 0 || i > SUPPORTED_CABLE_MAX) { | 121 | if (i == 0 || i > SUPPORTED_CABLE_MAX) { |
| 120 | err = -EINVAL; | ||
| 121 | dev_err(&pdev->dev, "error: pdata->cable_names size = %d\n", | 122 | dev_err(&pdev->dev, "error: pdata->cable_names size = %d\n", |
| 122 | i - 1); | 123 | i - 1); |
| 123 | goto out; | 124 | return -EINVAL; |
| 124 | } | 125 | } |
| 125 | data->num_cables = i; | 126 | data->num_cables = i; |
| 126 | 127 | ||
| 127 | if (!pdata->adc_conditions || | 128 | if (!pdata->adc_conditions || |
| 128 | !pdata->adc_conditions[0].state) { | 129 | !pdata->adc_conditions[0].state) { |
| 129 | err = -EINVAL; | ||
| 130 | dev_err(&pdev->dev, "error: adc_conditions not defined.\n"); | 130 | dev_err(&pdev->dev, "error: adc_conditions not defined.\n"); |
| 131 | goto out; | 131 | return -EINVAL; |
| 132 | } | 132 | } |
| 133 | data->adc_conditions = pdata->adc_conditions; | 133 | data->adc_conditions = pdata->adc_conditions; |
| 134 | 134 | ||
| @@ -138,10 +138,8 @@ static int adc_jack_probe(struct platform_device *pdev) | |||
| 138 | data->num_conditions = i; | 138 | data->num_conditions = i; |
| 139 | 139 | ||
| 140 | data->chan = iio_channel_get(&pdev->dev, pdata->consumer_channel); | 140 | data->chan = iio_channel_get(&pdev->dev, pdata->consumer_channel); |
| 141 | if (IS_ERR(data->chan)) { | 141 | if (IS_ERR(data->chan)) |
| 142 | err = PTR_ERR(data->chan); | 142 | return PTR_ERR(data->chan); |
| 143 | goto out; | ||
| 144 | } | ||
| 145 | 143 | ||
| 146 | data->handling_delay = msecs_to_jiffies(pdata->handling_delay_ms); | 144 | data->handling_delay = msecs_to_jiffies(pdata->handling_delay_ms); |
| 147 | 145 | ||
| @@ -149,15 +147,14 @@ static int adc_jack_probe(struct platform_device *pdev) | |||
| 149 | 147 | ||
| 150 | platform_set_drvdata(pdev, data); | 148 | platform_set_drvdata(pdev, data); |
| 151 | 149 | ||
| 152 | err = extcon_dev_register(&data->edev); | 150 | err = devm_extcon_dev_register(&pdev->dev, data->edev); |
| 153 | if (err) | 151 | if (err) |
| 154 | goto out; | 152 | return err; |
| 155 | 153 | ||
| 156 | data->irq = platform_get_irq(pdev, 0); | 154 | data->irq = platform_get_irq(pdev, 0); |
| 157 | if (!data->irq) { | 155 | if (!data->irq) { |
| 158 | dev_err(&pdev->dev, "platform_get_irq failed\n"); | 156 | dev_err(&pdev->dev, "platform_get_irq failed\n"); |
| 159 | err = -ENODEV; | 157 | return -ENODEV; |
| 160 | goto err_irq; | ||
| 161 | } | 158 | } |
| 162 | 159 | ||
| 163 | err = request_any_context_irq(data->irq, adc_jack_irq_thread, | 160 | err = request_any_context_irq(data->irq, adc_jack_irq_thread, |
| @@ -165,15 +162,10 @@ static int adc_jack_probe(struct platform_device *pdev) | |||
| 165 | 162 | ||
| 166 | if (err < 0) { | 163 | if (err < 0) { |
| 167 | dev_err(&pdev->dev, "error: irq %d\n", data->irq); | 164 | dev_err(&pdev->dev, "error: irq %d\n", data->irq); |
| 168 | goto err_irq; | 165 | return err; |
| 169 | } | 166 | } |
| 170 | 167 | ||
| 171 | return 0; | 168 | return 0; |
| 172 | |||
| 173 | err_irq: | ||
| 174 | extcon_dev_unregister(&data->edev); | ||
| 175 | out: | ||
| 176 | return err; | ||
| 177 | } | 169 | } |
| 178 | 170 | ||
| 179 | static int adc_jack_remove(struct platform_device *pdev) | 171 | static int adc_jack_remove(struct platform_device *pdev) |
| @@ -182,7 +174,6 @@ static int adc_jack_remove(struct platform_device *pdev) | |||
| 182 | 174 | ||
| 183 | free_irq(data->irq, data); | 175 | free_irq(data->irq, data); |
| 184 | cancel_work_sync(&data->handler.work); | 176 | cancel_work_sync(&data->handler.work); |
| 185 | extcon_dev_unregister(&data->edev); | ||
| 186 | 177 | ||
| 187 | return 0; | 178 | return 0; |
| 188 | } | 179 | } |
diff --git a/drivers/extcon/extcon-arizona.c b/drivers/extcon/extcon-arizona.c index 98a14f6143a7..6c84e3d12043 100644 --- a/drivers/extcon/extcon-arizona.c +++ b/drivers/extcon/extcon-arizona.c | |||
| @@ -91,7 +91,7 @@ struct arizona_extcon_info { | |||
| 91 | 91 | ||
| 92 | int hpdet_ip; | 92 | int hpdet_ip; |
| 93 | 93 | ||
| 94 | struct extcon_dev edev; | 94 | struct extcon_dev *edev; |
| 95 | }; | 95 | }; |
| 96 | 96 | ||
| 97 | static const struct arizona_micd_config micd_default_modes[] = { | 97 | static const struct arizona_micd_config micd_default_modes[] = { |
| @@ -546,7 +546,7 @@ static irqreturn_t arizona_hpdet_irq(int irq, void *data) | |||
| 546 | } | 546 | } |
| 547 | 547 | ||
| 548 | /* If the cable was removed while measuring ignore the result */ | 548 | /* If the cable was removed while measuring ignore the result */ |
| 549 | ret = extcon_get_cable_state_(&info->edev, ARIZONA_CABLE_MECHANICAL); | 549 | ret = extcon_get_cable_state_(info->edev, ARIZONA_CABLE_MECHANICAL); |
| 550 | if (ret < 0) { | 550 | if (ret < 0) { |
| 551 | dev_err(arizona->dev, "Failed to check cable state: %d\n", | 551 | dev_err(arizona->dev, "Failed to check cable state: %d\n", |
| 552 | ret); | 552 | ret); |
| @@ -581,7 +581,7 @@ static irqreturn_t arizona_hpdet_irq(int irq, void *data) | |||
| 581 | else | 581 | else |
| 582 | report = ARIZONA_CABLE_HEADPHONE; | 582 | report = ARIZONA_CABLE_HEADPHONE; |
| 583 | 583 | ||
| 584 | ret = extcon_set_cable_state_(&info->edev, report, true); | 584 | ret = extcon_set_cable_state_(info->edev, report, true); |
| 585 | if (ret != 0) | 585 | if (ret != 0) |
| 586 | dev_err(arizona->dev, "Failed to report HP/line: %d\n", | 586 | dev_err(arizona->dev, "Failed to report HP/line: %d\n", |
| 587 | ret); | 587 | ret); |
| @@ -664,7 +664,7 @@ err: | |||
| 664 | ARIZONA_ACCDET_MODE_MASK, ARIZONA_ACCDET_MODE_MIC); | 664 | ARIZONA_ACCDET_MODE_MASK, ARIZONA_ACCDET_MODE_MIC); |
| 665 | 665 | ||
| 666 | /* Just report headphone */ | 666 | /* Just report headphone */ |
| 667 | ret = extcon_update_state(&info->edev, | 667 | ret = extcon_update_state(info->edev, |
| 668 | 1 << ARIZONA_CABLE_HEADPHONE, | 668 | 1 << ARIZONA_CABLE_HEADPHONE, |
| 669 | 1 << ARIZONA_CABLE_HEADPHONE); | 669 | 1 << ARIZONA_CABLE_HEADPHONE); |
| 670 | if (ret != 0) | 670 | if (ret != 0) |
| @@ -723,7 +723,7 @@ err: | |||
| 723 | ARIZONA_ACCDET_MODE_MASK, ARIZONA_ACCDET_MODE_MIC); | 723 | ARIZONA_ACCDET_MODE_MASK, ARIZONA_ACCDET_MODE_MIC); |
| 724 | 724 | ||
| 725 | /* Just report headphone */ | 725 | /* Just report headphone */ |
| 726 | ret = extcon_update_state(&info->edev, | 726 | ret = extcon_update_state(info->edev, |
| 727 | 1 << ARIZONA_CABLE_HEADPHONE, | 727 | 1 << ARIZONA_CABLE_HEADPHONE, |
| 728 | 1 << ARIZONA_CABLE_HEADPHONE); | 728 | 1 << ARIZONA_CABLE_HEADPHONE); |
| 729 | if (ret != 0) | 729 | if (ret != 0) |
| @@ -764,7 +764,7 @@ static void arizona_micd_detect(struct work_struct *work) | |||
| 764 | mutex_lock(&info->lock); | 764 | mutex_lock(&info->lock); |
| 765 | 765 | ||
| 766 | /* If the cable was removed while measuring ignore the result */ | 766 | /* If the cable was removed while measuring ignore the result */ |
| 767 | ret = extcon_get_cable_state_(&info->edev, ARIZONA_CABLE_MECHANICAL); | 767 | ret = extcon_get_cable_state_(info->edev, ARIZONA_CABLE_MECHANICAL); |
| 768 | if (ret < 0) { | 768 | if (ret < 0) { |
| 769 | dev_err(arizona->dev, "Failed to check cable state: %d\n", | 769 | dev_err(arizona->dev, "Failed to check cable state: %d\n", |
| 770 | ret); | 770 | ret); |
| @@ -812,7 +812,7 @@ static void arizona_micd_detect(struct work_struct *work) | |||
| 812 | if (info->detecting && (val & ARIZONA_MICD_LVL_8)) { | 812 | if (info->detecting && (val & ARIZONA_MICD_LVL_8)) { |
| 813 | arizona_identify_headphone(info); | 813 | arizona_identify_headphone(info); |
| 814 | 814 | ||
| 815 | ret = extcon_update_state(&info->edev, | 815 | ret = extcon_update_state(info->edev, |
| 816 | 1 << ARIZONA_CABLE_MICROPHONE, | 816 | 1 << ARIZONA_CABLE_MICROPHONE, |
| 817 | 1 << ARIZONA_CABLE_MICROPHONE); | 817 | 1 << ARIZONA_CABLE_MICROPHONE); |
| 818 | 818 | ||
| @@ -999,7 +999,7 @@ static irqreturn_t arizona_jackdet(int irq, void *data) | |||
| 999 | 999 | ||
| 1000 | if (info->last_jackdet == present) { | 1000 | if (info->last_jackdet == present) { |
| 1001 | dev_dbg(arizona->dev, "Detected jack\n"); | 1001 | dev_dbg(arizona->dev, "Detected jack\n"); |
| 1002 | ret = extcon_set_cable_state_(&info->edev, | 1002 | ret = extcon_set_cable_state_(info->edev, |
| 1003 | ARIZONA_CABLE_MECHANICAL, true); | 1003 | ARIZONA_CABLE_MECHANICAL, true); |
| 1004 | 1004 | ||
| 1005 | if (ret != 0) | 1005 | if (ret != 0) |
| @@ -1038,7 +1038,7 @@ static irqreturn_t arizona_jackdet(int irq, void *data) | |||
| 1038 | info->micd_ranges[i].key, 0); | 1038 | info->micd_ranges[i].key, 0); |
| 1039 | input_sync(info->input); | 1039 | input_sync(info->input); |
| 1040 | 1040 | ||
| 1041 | ret = extcon_update_state(&info->edev, 0xffffffff, 0); | 1041 | ret = extcon_update_state(info->edev, 0xffffffff, 0); |
| 1042 | if (ret != 0) | 1042 | if (ret != 0) |
| 1043 | dev_err(arizona->dev, "Removal report failed: %d\n", | 1043 | dev_err(arizona->dev, "Removal report failed: %d\n", |
| 1044 | ret); | 1044 | ret); |
| @@ -1105,15 +1105,14 @@ static int arizona_extcon_probe(struct platform_device *pdev) | |||
| 1105 | info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL); | 1105 | info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL); |
| 1106 | if (!info) { | 1106 | if (!info) { |
| 1107 | dev_err(&pdev->dev, "Failed to allocate memory\n"); | 1107 | dev_err(&pdev->dev, "Failed to allocate memory\n"); |
| 1108 | ret = -ENOMEM; | 1108 | return -ENOMEM; |
| 1109 | goto err; | ||
| 1110 | } | 1109 | } |
| 1111 | 1110 | ||
| 1112 | info->micvdd = devm_regulator_get(arizona->dev, "MICVDD"); | 1111 | info->micvdd = devm_regulator_get(arizona->dev, "MICVDD"); |
| 1113 | if (IS_ERR(info->micvdd)) { | 1112 | if (IS_ERR(info->micvdd)) { |
| 1114 | ret = PTR_ERR(info->micvdd); | 1113 | ret = PTR_ERR(info->micvdd); |
| 1115 | dev_err(arizona->dev, "Failed to get MICVDD: %d\n", ret); | 1114 | dev_err(arizona->dev, "Failed to get MICVDD: %d\n", ret); |
| 1116 | goto err; | 1115 | return ret; |
| 1117 | } | 1116 | } |
| 1118 | 1117 | ||
| 1119 | mutex_init(&info->lock); | 1118 | mutex_init(&info->lock); |
| @@ -1151,15 +1150,19 @@ static int arizona_extcon_probe(struct platform_device *pdev) | |||
| 1151 | break; | 1150 | break; |
| 1152 | } | 1151 | } |
| 1153 | 1152 | ||
| 1154 | info->edev.name = "Headset Jack"; | 1153 | info->edev = devm_extcon_dev_allocate(&pdev->dev, arizona_cable); |
| 1155 | info->edev.dev.parent = arizona->dev; | 1154 | if (IS_ERR(info->edev)) { |
| 1156 | info->edev.supported_cable = arizona_cable; | 1155 | dev_err(&pdev->dev, "failed to allocate extcon device\n"); |
| 1156 | return -ENOMEM; | ||
| 1157 | } | ||
| 1158 | info->edev->name = "Headset Jack"; | ||
| 1159 | info->edev->dev.parent = arizona->dev; | ||
| 1157 | 1160 | ||
| 1158 | ret = extcon_dev_register(&info->edev); | 1161 | ret = devm_extcon_dev_register(&pdev->dev, info->edev); |
| 1159 | if (ret < 0) { | 1162 | if (ret < 0) { |
| 1160 | dev_err(arizona->dev, "extcon_dev_register() failed: %d\n", | 1163 | dev_err(arizona->dev, "extcon_dev_register() failed: %d\n", |
| 1161 | ret); | 1164 | ret); |
| 1162 | goto err; | 1165 | return ret; |
| 1163 | } | 1166 | } |
| 1164 | 1167 | ||
| 1165 | info->input = devm_input_allocate_device(&pdev->dev); | 1168 | info->input = devm_input_allocate_device(&pdev->dev); |
| @@ -1410,8 +1413,6 @@ err_rise: | |||
| 1410 | err_input: | 1413 | err_input: |
| 1411 | err_register: | 1414 | err_register: |
| 1412 | pm_runtime_disable(&pdev->dev); | 1415 | pm_runtime_disable(&pdev->dev); |
| 1413 | extcon_dev_unregister(&info->edev); | ||
| 1414 | err: | ||
| 1415 | return ret; | 1416 | return ret; |
| 1416 | } | 1417 | } |
| 1417 | 1418 | ||
| @@ -1445,7 +1446,6 @@ static int arizona_extcon_remove(struct platform_device *pdev) | |||
| 1445 | regmap_update_bits(arizona->regmap, ARIZONA_JACK_DETECT_ANALOGUE, | 1446 | regmap_update_bits(arizona->regmap, ARIZONA_JACK_DETECT_ANALOGUE, |
| 1446 | ARIZONA_JD1_ENA, 0); | 1447 | ARIZONA_JD1_ENA, 0); |
| 1447 | arizona_clk32k_disable(arizona); | 1448 | arizona_clk32k_disable(arizona); |
| 1448 | extcon_dev_unregister(&info->edev); | ||
| 1449 | 1449 | ||
| 1450 | return 0; | 1450 | return 0; |
| 1451 | } | 1451 | } |
diff --git a/drivers/extcon/extcon-class.c b/drivers/extcon/extcon-class.c index 7ab21aa6eaa1..18d42c0e4581 100644 --- a/drivers/extcon/extcon-class.c +++ b/drivers/extcon/extcon-class.c | |||
| @@ -565,6 +565,100 @@ static void dummy_sysfs_dev_release(struct device *dev) | |||
| 565 | { | 565 | { |
| 566 | } | 566 | } |
| 567 | 567 | ||
| 568 | /* | ||
| 569 | * extcon_dev_allocate() - Allocate the memory of extcon device. | ||
| 570 | * @supported_cable: Array of supported cable names ending with NULL. | ||
| 571 | * If supported_cable is NULL, cable name related APIs | ||
| 572 | * are disabled. | ||
| 573 | * | ||
| 574 | * This function allocates the memory for extcon device without allocating | ||
| 575 | * memory in each extcon provider driver and initialize default setting for | ||
| 576 | * extcon device. | ||
| 577 | * | ||
| 578 | * Return the pointer of extcon device if success or ERR_PTR(err) if fail | ||
| 579 | */ | ||
| 580 | struct extcon_dev *extcon_dev_allocate(const char **supported_cable) | ||
| 581 | { | ||
| 582 | struct extcon_dev *edev; | ||
| 583 | |||
| 584 | edev = kzalloc(sizeof(*edev), GFP_KERNEL); | ||
| 585 | if (!edev) | ||
| 586 | return ERR_PTR(-ENOMEM); | ||
| 587 | |||
| 588 | edev->max_supported = 0; | ||
| 589 | edev->supported_cable = supported_cable; | ||
| 590 | |||
| 591 | return edev; | ||
| 592 | } | ||
| 593 | |||
| 594 | /* | ||
| 595 | * extcon_dev_free() - Free the memory of extcon device. | ||
| 596 | * @edev: the extcon device to free | ||
| 597 | */ | ||
| 598 | void extcon_dev_free(struct extcon_dev *edev) | ||
| 599 | { | ||
| 600 | kfree(edev); | ||
| 601 | } | ||
| 602 | EXPORT_SYMBOL_GPL(extcon_dev_free); | ||
| 603 | |||
| 604 | static int devm_extcon_dev_match(struct device *dev, void *res, void *data) | ||
| 605 | { | ||
| 606 | struct extcon_dev **r = res; | ||
| 607 | |||
| 608 | if (WARN_ON(!r || !*r)) | ||
| 609 | return 0; | ||
| 610 | |||
| 611 | return *r == data; | ||
| 612 | } | ||
| 613 | |||
| 614 | static void devm_extcon_dev_release(struct device *dev, void *res) | ||
| 615 | { | ||
| 616 | extcon_dev_free(*(struct extcon_dev **)res); | ||
| 617 | } | ||
| 618 | |||
| 619 | /** | ||
| 620 | * devm_extcon_dev_allocate - Allocate managed extcon device | ||
| 621 | * @dev: device owning the extcon device being created | ||
| 622 | * @supported_cable: Array of supported cable names ending with NULL. | ||
| 623 | * If supported_cable is NULL, cable name related APIs | ||
| 624 | * are disabled. | ||
| 625 | * | ||
| 626 | * This function manages automatically the memory of extcon device using device | ||
| 627 | * resource management and simplify the control of freeing the memory of extcon | ||
| 628 | * device. | ||
| 629 | * | ||
| 630 | * Returns the pointer memory of allocated extcon_dev if success | ||
| 631 | * or ERR_PTR(err) if fail | ||
| 632 | */ | ||
| 633 | struct extcon_dev *devm_extcon_dev_allocate(struct device *dev, | ||
| 634 | const char **supported_cable) | ||
| 635 | { | ||
| 636 | struct extcon_dev **ptr, *edev; | ||
| 637 | |||
| 638 | ptr = devres_alloc(devm_extcon_dev_release, sizeof(*ptr), GFP_KERNEL); | ||
| 639 | if (!ptr) | ||
| 640 | return ERR_PTR(-ENOMEM); | ||
| 641 | |||
| 642 | edev = extcon_dev_allocate(supported_cable); | ||
| 643 | if (IS_ERR(edev)) { | ||
| 644 | devres_free(ptr); | ||
| 645 | return edev; | ||
| 646 | } | ||
| 647 | |||
| 648 | *ptr = edev; | ||
| 649 | devres_add(dev, ptr); | ||
| 650 | |||
| 651 | return edev; | ||
| 652 | } | ||
| 653 | EXPORT_SYMBOL_GPL(devm_extcon_dev_allocate); | ||
| 654 | |||
| 655 | void devm_extcon_dev_free(struct device *dev, struct extcon_dev *edev) | ||
| 656 | { | ||
| 657 | WARN_ON(devres_release(dev, devm_extcon_dev_release, | ||
| 658 | devm_extcon_dev_match, edev)); | ||
| 659 | } | ||
| 660 | EXPORT_SYMBOL_GPL(devm_extcon_dev_free); | ||
| 661 | |||
| 568 | /** | 662 | /** |
| 569 | * extcon_dev_register() - Register a new extcon device | 663 | * extcon_dev_register() - Register a new extcon device |
| 570 | * @edev : the new extcon device (should be allocated before calling) | 664 | * @edev : the new extcon device (should be allocated before calling) |
| @@ -819,6 +913,63 @@ void extcon_dev_unregister(struct extcon_dev *edev) | |||
| 819 | } | 913 | } |
| 820 | EXPORT_SYMBOL_GPL(extcon_dev_unregister); | 914 | EXPORT_SYMBOL_GPL(extcon_dev_unregister); |
| 821 | 915 | ||
| 916 | static void devm_extcon_dev_unreg(struct device *dev, void *res) | ||
| 917 | { | ||
| 918 | extcon_dev_unregister(*(struct extcon_dev **)res); | ||
| 919 | } | ||
| 920 | |||
| 921 | /** | ||
| 922 | * devm_extcon_dev_register() - Resource-managed extcon_dev_register() | ||
| 923 | * @dev: device to allocate extcon device | ||
| 924 | * @edev: the new extcon device to register | ||
| 925 | * | ||
| 926 | * Managed extcon_dev_register() function. If extcon device is attached with | ||
| 927 | * this function, that extcon device is automatically unregistered on driver | ||
| 928 | * detach. Internally this function calls extcon_dev_register() function. | ||
| 929 | * To get more information, refer that function. | ||
| 930 | * | ||
| 931 | * If extcon device is registered with this function and the device needs to be | ||
| 932 | * unregistered separately, devm_extcon_dev_unregister() should be used. | ||
| 933 | * | ||
| 934 | * Returns 0 if success or negaive error number if failure. | ||
| 935 | */ | ||
| 936 | int devm_extcon_dev_register(struct device *dev, struct extcon_dev *edev) | ||
| 937 | { | ||
| 938 | struct extcon_dev **ptr; | ||
| 939 | int ret; | ||
| 940 | |||
| 941 | ptr = devres_alloc(devm_extcon_dev_unreg, sizeof(*ptr), GFP_KERNEL); | ||
| 942 | if (!ptr) | ||
| 943 | return -ENOMEM; | ||
| 944 | |||
| 945 | ret = extcon_dev_register(edev); | ||
| 946 | if (ret) { | ||
| 947 | devres_free(ptr); | ||
| 948 | return ret; | ||
| 949 | } | ||
| 950 | |||
| 951 | *ptr = edev; | ||
| 952 | devres_add(dev, ptr); | ||
| 953 | |||
| 954 | return 0; | ||
| 955 | } | ||
| 956 | EXPORT_SYMBOL_GPL(devm_extcon_dev_register); | ||
| 957 | |||
| 958 | /** | ||
| 959 | * devm_extcon_dev_unregister() - Resource-managed extcon_dev_unregister() | ||
| 960 | * @dev: device the extcon belongs to | ||
| 961 | * @edev: the extcon device to unregister | ||
| 962 | * | ||
| 963 | * Unregister extcon device that is registered with devm_extcon_dev_register() | ||
| 964 | * function. | ||
| 965 | */ | ||
| 966 | void devm_extcon_dev_unregister(struct device *dev, struct extcon_dev *edev) | ||
| 967 | { | ||
| 968 | WARN_ON(devres_release(dev, devm_extcon_dev_unreg, | ||
| 969 | devm_extcon_dev_match, edev)); | ||
| 970 | } | ||
| 971 | EXPORT_SYMBOL_GPL(devm_extcon_dev_unregister); | ||
| 972 | |||
| 822 | #ifdef CONFIG_OF | 973 | #ifdef CONFIG_OF |
| 823 | /* | 974 | /* |
| 824 | * extcon_get_edev_by_phandle - Get the extcon device from devicetree | 975 | * extcon_get_edev_by_phandle - Get the extcon device from devicetree |
diff --git a/drivers/extcon/extcon-gpio.c b/drivers/extcon/extcon-gpio.c index 13d522255d81..645b28356819 100644 --- a/drivers/extcon/extcon-gpio.c +++ b/drivers/extcon/extcon-gpio.c | |||
| @@ -32,7 +32,7 @@ | |||
| 32 | #include <linux/extcon/extcon-gpio.h> | 32 | #include <linux/extcon/extcon-gpio.h> |
| 33 | 33 | ||
| 34 | struct gpio_extcon_data { | 34 | struct gpio_extcon_data { |
| 35 | struct extcon_dev edev; | 35 | struct extcon_dev *edev; |
| 36 | unsigned gpio; | 36 | unsigned gpio; |
| 37 | bool gpio_active_low; | 37 | bool gpio_active_low; |
| 38 | const char *state_on; | 38 | const char *state_on; |
| @@ -53,7 +53,7 @@ static void gpio_extcon_work(struct work_struct *work) | |||
| 53 | state = gpio_get_value(data->gpio); | 53 | state = gpio_get_value(data->gpio); |
| 54 | if (data->gpio_active_low) | 54 | if (data->gpio_active_low) |
| 55 | state = !state; | 55 | state = !state; |
| 56 | extcon_set_state(&data->edev, state); | 56 | extcon_set_state(data->edev, state); |
| 57 | } | 57 | } |
| 58 | 58 | ||
| 59 | static irqreturn_t gpio_irq_handler(int irq, void *dev_id) | 59 | static irqreturn_t gpio_irq_handler(int irq, void *dev_id) |
| @@ -67,9 +67,10 @@ static irqreturn_t gpio_irq_handler(int irq, void *dev_id) | |||
| 67 | 67 | ||
| 68 | static ssize_t extcon_gpio_print_state(struct extcon_dev *edev, char *buf) | 68 | static ssize_t extcon_gpio_print_state(struct extcon_dev *edev, char *buf) |
| 69 | { | 69 | { |
| 70 | struct gpio_extcon_data *extcon_data = | 70 | struct device *dev = edev->dev.parent; |
| 71 | container_of(edev, struct gpio_extcon_data, edev); | 71 | struct gpio_extcon_data *extcon_data = dev_get_drvdata(dev); |
| 72 | const char *state; | 72 | const char *state; |
| 73 | |||
| 73 | if (extcon_get_state(edev)) | 74 | if (extcon_get_state(edev)) |
| 74 | state = extcon_data->state_on; | 75 | state = extcon_data->state_on; |
| 75 | else | 76 | else |
| @@ -98,15 +99,21 @@ static int gpio_extcon_probe(struct platform_device *pdev) | |||
| 98 | if (!extcon_data) | 99 | if (!extcon_data) |
| 99 | return -ENOMEM; | 100 | return -ENOMEM; |
| 100 | 101 | ||
| 101 | extcon_data->edev.name = pdata->name; | 102 | extcon_data->edev = devm_extcon_dev_allocate(&pdev->dev, NULL); |
| 102 | extcon_data->edev.dev.parent = &pdev->dev; | 103 | if (IS_ERR(extcon_data->edev)) { |
| 104 | dev_err(&pdev->dev, "failed to allocate extcon device\n"); | ||
| 105 | return -ENOMEM; | ||
| 106 | } | ||
| 107 | extcon_data->edev->name = pdata->name; | ||
| 108 | extcon_data->edev->dev.parent = &pdev->dev; | ||
| 109 | |||
| 103 | extcon_data->gpio = pdata->gpio; | 110 | extcon_data->gpio = pdata->gpio; |
| 104 | extcon_data->gpio_active_low = pdata->gpio_active_low; | 111 | extcon_data->gpio_active_low = pdata->gpio_active_low; |
| 105 | extcon_data->state_on = pdata->state_on; | 112 | extcon_data->state_on = pdata->state_on; |
| 106 | extcon_data->state_off = pdata->state_off; | 113 | extcon_data->state_off = pdata->state_off; |
| 107 | extcon_data->check_on_resume = pdata->check_on_resume; | 114 | extcon_data->check_on_resume = pdata->check_on_resume; |
| 108 | if (pdata->state_on && pdata->state_off) | 115 | if (pdata->state_on && pdata->state_off) |
| 109 | extcon_data->edev.print_state = extcon_gpio_print_state; | 116 | extcon_data->edev->print_state = extcon_gpio_print_state; |
| 110 | 117 | ||
| 111 | ret = devm_gpio_request_one(&pdev->dev, extcon_data->gpio, GPIOF_DIR_IN, | 118 | ret = devm_gpio_request_one(&pdev->dev, extcon_data->gpio, GPIOF_DIR_IN, |
| 112 | pdev->name); | 119 | pdev->name); |
| @@ -121,34 +128,27 @@ static int gpio_extcon_probe(struct platform_device *pdev) | |||
| 121 | msecs_to_jiffies(pdata->debounce); | 128 | msecs_to_jiffies(pdata->debounce); |
| 122 | } | 129 | } |
| 123 | 130 | ||
| 124 | ret = extcon_dev_register(&extcon_data->edev); | 131 | ret = devm_extcon_dev_register(&pdev->dev, extcon_data->edev); |
| 125 | if (ret < 0) | 132 | if (ret < 0) |
| 126 | return ret; | 133 | return ret; |
| 127 | 134 | ||
| 128 | INIT_DELAYED_WORK(&extcon_data->work, gpio_extcon_work); | 135 | INIT_DELAYED_WORK(&extcon_data->work, gpio_extcon_work); |
| 129 | 136 | ||
| 130 | extcon_data->irq = gpio_to_irq(extcon_data->gpio); | 137 | extcon_data->irq = gpio_to_irq(extcon_data->gpio); |
| 131 | if (extcon_data->irq < 0) { | 138 | if (extcon_data->irq < 0) |
| 132 | ret = extcon_data->irq; | 139 | return extcon_data->irq; |
| 133 | goto err; | ||
| 134 | } | ||
| 135 | 140 | ||
| 136 | ret = request_any_context_irq(extcon_data->irq, gpio_irq_handler, | 141 | ret = request_any_context_irq(extcon_data->irq, gpio_irq_handler, |
| 137 | pdata->irq_flags, pdev->name, | 142 | pdata->irq_flags, pdev->name, |
| 138 | extcon_data); | 143 | extcon_data); |
| 139 | if (ret < 0) | 144 | if (ret < 0) |
| 140 | goto err; | 145 | return ret; |
| 141 | 146 | ||
| 142 | platform_set_drvdata(pdev, extcon_data); | 147 | platform_set_drvdata(pdev, extcon_data); |
| 143 | /* Perform initial detection */ | 148 | /* Perform initial detection */ |
| 144 | gpio_extcon_work(&extcon_data->work.work); | 149 | gpio_extcon_work(&extcon_data->work.work); |
| 145 | 150 | ||
| 146 | return 0; | 151 | return 0; |
| 147 | |||
| 148 | err: | ||
| 149 | extcon_dev_unregister(&extcon_data->edev); | ||
| 150 | |||
| 151 | return ret; | ||
| 152 | } | 152 | } |
| 153 | 153 | ||
| 154 | static int gpio_extcon_remove(struct platform_device *pdev) | 154 | static int gpio_extcon_remove(struct platform_device *pdev) |
| @@ -157,7 +157,6 @@ static int gpio_extcon_remove(struct platform_device *pdev) | |||
| 157 | 157 | ||
| 158 | cancel_delayed_work_sync(&extcon_data->work); | 158 | cancel_delayed_work_sync(&extcon_data->work); |
| 159 | free_irq(extcon_data->irq, extcon_data); | 159 | free_irq(extcon_data->irq, extcon_data); |
| 160 | extcon_dev_unregister(&extcon_data->edev); | ||
| 161 | 160 | ||
| 162 | return 0; | 161 | return 0; |
| 163 | } | 162 | } |
diff --git a/drivers/extcon/extcon-max14577.c b/drivers/extcon/extcon-max14577.c index 3846941801b8..d49e891b5675 100644 --- a/drivers/extcon/extcon-max14577.c +++ b/drivers/extcon/extcon-max14577.c | |||
| @@ -1,8 +1,9 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * extcon-max14577.c - MAX14577 extcon driver to support MAX14577 MUIC | 2 | * extcon-max14577.c - MAX14577/77836 extcon driver to support MUIC |
| 3 | * | 3 | * |
| 4 | * Copyright (C) 2013 Samsung Electrnoics | 4 | * Copyright (C) 2013,2014 Samsung Electrnoics |
| 5 | * Chanwoo Choi <cw00.choi@samsung.com> | 5 | * Chanwoo Choi <cw00.choi@samsung.com> |
| 6 | * Krzysztof Kozlowski <k.kozlowski@samsung.com> | ||
| 6 | * | 7 | * |
| 7 | * This program is free software; you can redistribute it and/or modify | 8 | * This program is free software; you can redistribute it and/or modify |
| 8 | * it under the terms of the GNU General Public License as published by | 9 | * it under the terms of the GNU General Public License as published by |
| @@ -24,7 +25,6 @@ | |||
| 24 | #include <linux/mfd/max14577-private.h> | 25 | #include <linux/mfd/max14577-private.h> |
| 25 | #include <linux/extcon.h> | 26 | #include <linux/extcon.h> |
| 26 | 27 | ||
| 27 | #define DEV_NAME "max14577-muic" | ||
| 28 | #define DELAY_MS_DEFAULT 17000 /* unit: millisecond */ | 28 | #define DELAY_MS_DEFAULT 17000 /* unit: millisecond */ |
| 29 | 29 | ||
| 30 | enum max14577_muic_adc_debounce_time { | 30 | enum max14577_muic_adc_debounce_time { |
| @@ -40,6 +40,42 @@ enum max14577_muic_status { | |||
| 40 | MAX14577_MUIC_STATUS_END, | 40 | MAX14577_MUIC_STATUS_END, |
| 41 | }; | 41 | }; |
| 42 | 42 | ||
| 43 | /** | ||
| 44 | * struct max14577_muic_irq | ||
| 45 | * @irq: the index of irq list of MUIC device. | ||
| 46 | * @name: the name of irq. | ||
| 47 | * @virq: the virtual irq to use irq domain | ||
| 48 | */ | ||
| 49 | struct max14577_muic_irq { | ||
| 50 | unsigned int irq; | ||
| 51 | const char *name; | ||
| 52 | unsigned int virq; | ||
| 53 | }; | ||
| 54 | |||
| 55 | static struct max14577_muic_irq max14577_muic_irqs[] = { | ||
| 56 | { MAX14577_IRQ_INT1_ADC, "muic-ADC" }, | ||
| 57 | { MAX14577_IRQ_INT1_ADCLOW, "muic-ADCLOW" }, | ||
| 58 | { MAX14577_IRQ_INT1_ADCERR, "muic-ADCError" }, | ||
| 59 | { MAX14577_IRQ_INT2_CHGTYP, "muic-CHGTYP" }, | ||
| 60 | { MAX14577_IRQ_INT2_CHGDETRUN, "muic-CHGDETRUN" }, | ||
| 61 | { MAX14577_IRQ_INT2_DCDTMR, "muic-DCDTMR" }, | ||
| 62 | { MAX14577_IRQ_INT2_DBCHG, "muic-DBCHG" }, | ||
| 63 | { MAX14577_IRQ_INT2_VBVOLT, "muic-VBVOLT" }, | ||
| 64 | }; | ||
| 65 | |||
| 66 | static struct max14577_muic_irq max77836_muic_irqs[] = { | ||
| 67 | { MAX14577_IRQ_INT1_ADC, "muic-ADC" }, | ||
| 68 | { MAX14577_IRQ_INT1_ADCLOW, "muic-ADCLOW" }, | ||
| 69 | { MAX14577_IRQ_INT1_ADCERR, "muic-ADCError" }, | ||
| 70 | { MAX77836_IRQ_INT1_ADC1K, "muic-ADC1K" }, | ||
| 71 | { MAX14577_IRQ_INT2_CHGTYP, "muic-CHGTYP" }, | ||
| 72 | { MAX14577_IRQ_INT2_CHGDETRUN, "muic-CHGDETRUN" }, | ||
| 73 | { MAX14577_IRQ_INT2_DCDTMR, "muic-DCDTMR" }, | ||
| 74 | { MAX14577_IRQ_INT2_DBCHG, "muic-DBCHG" }, | ||
| 75 | { MAX14577_IRQ_INT2_VBVOLT, "muic-VBVOLT" }, | ||
| 76 | { MAX77836_IRQ_INT2_VIDRM, "muic-VIDRM" }, | ||
| 77 | }; | ||
| 78 | |||
| 43 | struct max14577_muic_info { | 79 | struct max14577_muic_info { |
| 44 | struct device *dev; | 80 | struct device *dev; |
| 45 | struct max14577 *max14577; | 81 | struct max14577 *max14577; |
| @@ -48,6 +84,8 @@ struct max14577_muic_info { | |||
| 48 | int prev_chg_type; | 84 | int prev_chg_type; |
| 49 | u8 status[MAX14577_MUIC_STATUS_END]; | 85 | u8 status[MAX14577_MUIC_STATUS_END]; |
| 50 | 86 | ||
| 87 | struct max14577_muic_irq *muic_irqs; | ||
| 88 | unsigned int muic_irqs_num; | ||
| 51 | bool irq_adc; | 89 | bool irq_adc; |
| 52 | bool irq_chg; | 90 | bool irq_chg; |
| 53 | struct work_struct irq_work; | 91 | struct work_struct irq_work; |
| @@ -74,29 +112,6 @@ enum max14577_muic_cable_group { | |||
| 74 | MAX14577_CABLE_GROUP_CHG, | 112 | MAX14577_CABLE_GROUP_CHG, |
| 75 | }; | 113 | }; |
| 76 | 114 | ||
| 77 | /** | ||
| 78 | * struct max14577_muic_irq | ||
| 79 | * @irq: the index of irq list of MUIC device. | ||
| 80 | * @name: the name of irq. | ||
| 81 | * @virq: the virtual irq to use irq domain | ||
| 82 | */ | ||
| 83 | struct max14577_muic_irq { | ||
| 84 | unsigned int irq; | ||
| 85 | const char *name; | ||
| 86 | unsigned int virq; | ||
| 87 | }; | ||
| 88 | |||
| 89 | static struct max14577_muic_irq muic_irqs[] = { | ||
| 90 | { MAX14577_IRQ_INT1_ADC, "muic-ADC" }, | ||
| 91 | { MAX14577_IRQ_INT1_ADCLOW, "muic-ADCLOW" }, | ||
| 92 | { MAX14577_IRQ_INT1_ADCERR, "muic-ADCError" }, | ||
| 93 | { MAX14577_IRQ_INT2_CHGTYP, "muic-CHGTYP" }, | ||
| 94 | { MAX14577_IRQ_INT2_CHGDETRUN, "muic-CHGDETRUN" }, | ||
| 95 | { MAX14577_IRQ_INT2_DCDTMR, "muic-DCDTMR" }, | ||
| 96 | { MAX14577_IRQ_INT2_DBCHG, "muic-DBCHG" }, | ||
| 97 | { MAX14577_IRQ_INT2_VBVOLT, "muic-VBVOLT" }, | ||
| 98 | }; | ||
| 99 | |||
| 100 | /* Define supported accessory type */ | 115 | /* Define supported accessory type */ |
| 101 | enum max14577_muic_acc_type { | 116 | enum max14577_muic_acc_type { |
| 102 | MAX14577_MUIC_ADC_GROUND = 0x0, | 117 | MAX14577_MUIC_ADC_GROUND = 0x0, |
| @@ -528,21 +543,12 @@ static void max14577_muic_irq_work(struct work_struct *work) | |||
| 528 | return; | 543 | return; |
| 529 | } | 544 | } |
| 530 | 545 | ||
| 531 | static irqreturn_t max14577_muic_irq_handler(int irq, void *data) | 546 | /* |
| 547 | * Sets irq_adc or irq_chg in max14577_muic_info and returns 1. | ||
| 548 | * Returns 0 if irq_type does not match registered IRQ for this device type. | ||
| 549 | */ | ||
| 550 | static int max14577_parse_irq(struct max14577_muic_info *info, int irq_type) | ||
| 532 | { | 551 | { |
| 533 | struct max14577_muic_info *info = data; | ||
| 534 | int i, irq_type = -1; | ||
| 535 | |||
| 536 | /* | ||
| 537 | * We may be called multiple times for different nested IRQ-s. | ||
| 538 | * Including changes in INT1_ADC and INT2_CGHTYP at once. | ||
| 539 | * However we only need to know whether it was ADC, charger | ||
| 540 | * or both interrupts so decode IRQ and turn on proper flags. | ||
| 541 | */ | ||
| 542 | for (i = 0; i < ARRAY_SIZE(muic_irqs); i++) | ||
| 543 | if (irq == muic_irqs[i].virq) | ||
| 544 | irq_type = muic_irqs[i].irq; | ||
| 545 | |||
| 546 | switch (irq_type) { | 552 | switch (irq_type) { |
| 547 | case MAX14577_IRQ_INT1_ADC: | 553 | case MAX14577_IRQ_INT1_ADC: |
| 548 | case MAX14577_IRQ_INT1_ADCLOW: | 554 | case MAX14577_IRQ_INT1_ADCLOW: |
| @@ -550,7 +556,7 @@ static irqreturn_t max14577_muic_irq_handler(int irq, void *data) | |||
| 550 | /* Handle all of accessory except for | 556 | /* Handle all of accessory except for |
| 551 | type of charger accessory */ | 557 | type of charger accessory */ |
| 552 | info->irq_adc = true; | 558 | info->irq_adc = true; |
| 553 | break; | 559 | return 1; |
| 554 | case MAX14577_IRQ_INT2_CHGTYP: | 560 | case MAX14577_IRQ_INT2_CHGTYP: |
| 555 | case MAX14577_IRQ_INT2_CHGDETRUN: | 561 | case MAX14577_IRQ_INT2_CHGDETRUN: |
| 556 | case MAX14577_IRQ_INT2_DCDTMR: | 562 | case MAX14577_IRQ_INT2_DCDTMR: |
| @@ -558,8 +564,62 @@ static irqreturn_t max14577_muic_irq_handler(int irq, void *data) | |||
| 558 | case MAX14577_IRQ_INT2_VBVOLT: | 564 | case MAX14577_IRQ_INT2_VBVOLT: |
| 559 | /* Handle charger accessory */ | 565 | /* Handle charger accessory */ |
| 560 | info->irq_chg = true; | 566 | info->irq_chg = true; |
| 567 | return 1; | ||
| 568 | default: | ||
| 569 | return 0; | ||
| 570 | } | ||
| 571 | } | ||
| 572 | |||
| 573 | /* | ||
| 574 | * Sets irq_adc or irq_chg in max14577_muic_info and returns 1. | ||
| 575 | * Returns 0 if irq_type does not match registered IRQ for this device type. | ||
| 576 | */ | ||
| 577 | static int max77836_parse_irq(struct max14577_muic_info *info, int irq_type) | ||
| 578 | { | ||
| 579 | /* First check common max14577 interrupts */ | ||
| 580 | if (max14577_parse_irq(info, irq_type)) | ||
| 581 | return 1; | ||
| 582 | |||
| 583 | switch (irq_type) { | ||
| 584 | case MAX77836_IRQ_INT1_ADC1K: | ||
| 585 | info->irq_adc = true; | ||
| 586 | return 1; | ||
| 587 | case MAX77836_IRQ_INT2_VIDRM: | ||
| 588 | /* Handle charger accessory */ | ||
| 589 | info->irq_chg = true; | ||
| 590 | return 1; | ||
| 591 | default: | ||
| 592 | return 0; | ||
| 593 | } | ||
| 594 | } | ||
| 595 | |||
| 596 | static irqreturn_t max14577_muic_irq_handler(int irq, void *data) | ||
| 597 | { | ||
| 598 | struct max14577_muic_info *info = data; | ||
| 599 | int i, irq_type = -1; | ||
| 600 | bool irq_parsed; | ||
| 601 | |||
| 602 | /* | ||
| 603 | * We may be called multiple times for different nested IRQ-s. | ||
| 604 | * Including changes in INT1_ADC and INT2_CGHTYP at once. | ||
| 605 | * However we only need to know whether it was ADC, charger | ||
| 606 | * or both interrupts so decode IRQ and turn on proper flags. | ||
| 607 | */ | ||
| 608 | for (i = 0; i < info->muic_irqs_num; i++) | ||
| 609 | if (irq == info->muic_irqs[i].virq) | ||
| 610 | irq_type = info->muic_irqs[i].irq; | ||
| 611 | |||
| 612 | switch (info->max14577->dev_type) { | ||
| 613 | case MAXIM_DEVICE_TYPE_MAX77836: | ||
| 614 | irq_parsed = max77836_parse_irq(info, irq_type); | ||
| 561 | break; | 615 | break; |
| 616 | case MAXIM_DEVICE_TYPE_MAX14577: | ||
| 562 | default: | 617 | default: |
| 618 | irq_parsed = max14577_parse_irq(info, irq_type); | ||
| 619 | break; | ||
| 620 | } | ||
| 621 | |||
| 622 | if (!irq_parsed) { | ||
| 563 | dev_err(info->dev, "muic interrupt: irq %d occurred, skipped\n", | 623 | dev_err(info->dev, "muic interrupt: irq %d occurred, skipped\n", |
| 564 | irq_type); | 624 | irq_type); |
| 565 | return IRQ_HANDLED; | 625 | return IRQ_HANDLED; |
| @@ -644,13 +704,24 @@ static int max14577_muic_probe(struct platform_device *pdev) | |||
| 644 | 704 | ||
| 645 | INIT_WORK(&info->irq_work, max14577_muic_irq_work); | 705 | INIT_WORK(&info->irq_work, max14577_muic_irq_work); |
| 646 | 706 | ||
| 707 | switch (max14577->dev_type) { | ||
| 708 | case MAXIM_DEVICE_TYPE_MAX77836: | ||
| 709 | info->muic_irqs = max77836_muic_irqs; | ||
| 710 | info->muic_irqs_num = ARRAY_SIZE(max77836_muic_irqs); | ||
| 711 | break; | ||
| 712 | case MAXIM_DEVICE_TYPE_MAX14577: | ||
| 713 | default: | ||
| 714 | info->muic_irqs = max14577_muic_irqs; | ||
| 715 | info->muic_irqs_num = ARRAY_SIZE(max14577_muic_irqs); | ||
| 716 | } | ||
| 717 | |||
| 647 | /* Support irq domain for max14577 MUIC device */ | 718 | /* Support irq domain for max14577 MUIC device */ |
| 648 | for (i = 0; i < ARRAY_SIZE(muic_irqs); i++) { | 719 | for (i = 0; i < info->muic_irqs_num; i++) { |
| 649 | struct max14577_muic_irq *muic_irq = &muic_irqs[i]; | 720 | struct max14577_muic_irq *muic_irq = &info->muic_irqs[i]; |
| 650 | unsigned int virq = 0; | 721 | unsigned int virq = 0; |
| 651 | 722 | ||
| 652 | virq = regmap_irq_get_virq(max14577->irq_data, muic_irq->irq); | 723 | virq = regmap_irq_get_virq(max14577->irq_data, muic_irq->irq); |
| 653 | if (!virq) | 724 | if (virq <= 0) |
| 654 | return -EINVAL; | 725 | return -EINVAL; |
| 655 | muic_irq->virq = virq; | 726 | muic_irq->virq = virq; |
| 656 | 727 | ||
| @@ -668,14 +739,16 @@ static int max14577_muic_probe(struct platform_device *pdev) | |||
| 668 | } | 739 | } |
| 669 | 740 | ||
| 670 | /* Initialize extcon device */ | 741 | /* Initialize extcon device */ |
| 671 | info->edev = devm_kzalloc(&pdev->dev, sizeof(*info->edev), GFP_KERNEL); | 742 | info->edev = devm_extcon_dev_allocate(&pdev->dev, |
| 672 | if (!info->edev) { | 743 | max14577_extcon_cable); |
| 744 | if (IS_ERR(info->edev)) { | ||
| 673 | dev_err(&pdev->dev, "failed to allocate memory for extcon\n"); | 745 | dev_err(&pdev->dev, "failed to allocate memory for extcon\n"); |
| 674 | return -ENOMEM; | 746 | return -ENOMEM; |
| 675 | } | 747 | } |
| 676 | info->edev->name = DEV_NAME; | 748 | |
| 677 | info->edev->supported_cable = max14577_extcon_cable; | 749 | info->edev->name = dev_name(&pdev->dev); |
| 678 | ret = extcon_dev_register(info->edev); | 750 | |
| 751 | ret = devm_extcon_dev_register(&pdev->dev, info->edev); | ||
| 679 | if (ret) { | 752 | if (ret) { |
| 680 | dev_err(&pdev->dev, "failed to register extcon device\n"); | 753 | dev_err(&pdev->dev, "failed to register extcon device\n"); |
| 681 | return ret; | 754 | return ret; |
| @@ -694,7 +767,7 @@ static int max14577_muic_probe(struct platform_device *pdev) | |||
| 694 | MAX14577_REG_DEVICEID, &id); | 767 | MAX14577_REG_DEVICEID, &id); |
| 695 | if (ret < 0) { | 768 | if (ret < 0) { |
| 696 | dev_err(&pdev->dev, "failed to read revision number\n"); | 769 | dev_err(&pdev->dev, "failed to read revision number\n"); |
| 697 | goto err_extcon; | 770 | return ret; |
| 698 | } | 771 | } |
| 699 | dev_info(info->dev, "device ID : 0x%x\n", id); | 772 | dev_info(info->dev, "device ID : 0x%x\n", id); |
| 700 | 773 | ||
| @@ -710,19 +783,10 @@ static int max14577_muic_probe(struct platform_device *pdev) | |||
| 710 | * driver should notify cable state to upper layer. | 783 | * driver should notify cable state to upper layer. |
| 711 | */ | 784 | */ |
| 712 | INIT_DELAYED_WORK(&info->wq_detcable, max14577_muic_detect_cable_wq); | 785 | INIT_DELAYED_WORK(&info->wq_detcable, max14577_muic_detect_cable_wq); |
| 713 | ret = queue_delayed_work(system_power_efficient_wq, &info->wq_detcable, | 786 | queue_delayed_work(system_power_efficient_wq, &info->wq_detcable, |
| 714 | delay_jiffies); | 787 | delay_jiffies); |
| 715 | if (ret < 0) { | ||
| 716 | dev_err(&pdev->dev, | ||
| 717 | "failed to schedule delayed work for cable detect\n"); | ||
| 718 | goto err_extcon; | ||
| 719 | } | ||
| 720 | 788 | ||
| 721 | return ret; | 789 | return ret; |
| 722 | |||
| 723 | err_extcon: | ||
| 724 | extcon_dev_unregister(info->edev); | ||
| 725 | return ret; | ||
| 726 | } | 790 | } |
| 727 | 791 | ||
| 728 | static int max14577_muic_remove(struct platform_device *pdev) | 792 | static int max14577_muic_remove(struct platform_device *pdev) |
| @@ -730,23 +794,30 @@ static int max14577_muic_remove(struct platform_device *pdev) | |||
| 730 | struct max14577_muic_info *info = platform_get_drvdata(pdev); | 794 | struct max14577_muic_info *info = platform_get_drvdata(pdev); |
| 731 | 795 | ||
| 732 | cancel_work_sync(&info->irq_work); | 796 | cancel_work_sync(&info->irq_work); |
| 733 | extcon_dev_unregister(info->edev); | ||
| 734 | 797 | ||
| 735 | return 0; | 798 | return 0; |
| 736 | } | 799 | } |
| 737 | 800 | ||
| 801 | static const struct platform_device_id max14577_muic_id[] = { | ||
| 802 | { "max14577-muic", MAXIM_DEVICE_TYPE_MAX14577, }, | ||
| 803 | { "max77836-muic", MAXIM_DEVICE_TYPE_MAX77836, }, | ||
| 804 | { } | ||
| 805 | }; | ||
| 806 | MODULE_DEVICE_TABLE(platform, max14577_muic_id); | ||
| 807 | |||
| 738 | static struct platform_driver max14577_muic_driver = { | 808 | static struct platform_driver max14577_muic_driver = { |
| 739 | .driver = { | 809 | .driver = { |
| 740 | .name = DEV_NAME, | 810 | .name = "max14577-muic", |
| 741 | .owner = THIS_MODULE, | 811 | .owner = THIS_MODULE, |
| 742 | }, | 812 | }, |
| 743 | .probe = max14577_muic_probe, | 813 | .probe = max14577_muic_probe, |
| 744 | .remove = max14577_muic_remove, | 814 | .remove = max14577_muic_remove, |
| 815 | .id_table = max14577_muic_id, | ||
| 745 | }; | 816 | }; |
| 746 | 817 | ||
| 747 | module_platform_driver(max14577_muic_driver); | 818 | module_platform_driver(max14577_muic_driver); |
| 748 | 819 | ||
| 749 | MODULE_DESCRIPTION("MAXIM 14577 Extcon driver"); | 820 | MODULE_DESCRIPTION("Maxim 14577/77836 Extcon driver"); |
| 750 | MODULE_AUTHOR("Chanwoo Choi <cw00.choi@samsung.com>"); | 821 | MODULE_AUTHOR("Chanwoo Choi <cw00.choi@samsung.com>, Krzysztof Kozlowski <k.kozlowski@samsung.com>"); |
| 751 | MODULE_LICENSE("GPL"); | 822 | MODULE_LICENSE("GPL"); |
| 752 | MODULE_ALIAS("platform:extcon-max14577"); | 823 | MODULE_ALIAS("platform:extcon-max14577"); |
diff --git a/drivers/extcon/extcon-max77693.c b/drivers/extcon/extcon-max77693.c index da268fbc901b..2c7c3e191591 100644 --- a/drivers/extcon/extcon-max77693.c +++ b/drivers/extcon/extcon-max77693.c | |||
| @@ -1175,25 +1175,24 @@ static int max77693_muic_probe(struct platform_device *pdev) | |||
| 1175 | } | 1175 | } |
| 1176 | 1176 | ||
| 1177 | /* Initialize extcon device */ | 1177 | /* Initialize extcon device */ |
| 1178 | info->edev = devm_kzalloc(&pdev->dev, sizeof(struct extcon_dev), | 1178 | info->edev = devm_extcon_dev_allocate(&pdev->dev, |
| 1179 | GFP_KERNEL); | 1179 | max77693_extcon_cable); |
| 1180 | if (!info->edev) { | 1180 | if (IS_ERR(info->edev)) { |
| 1181 | dev_err(&pdev->dev, "failed to allocate memory for extcon\n"); | 1181 | dev_err(&pdev->dev, "failed to allocate memory for extcon\n"); |
| 1182 | ret = -ENOMEM; | 1182 | ret = -ENOMEM; |
| 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; | 1186 | info->edev->dev.parent = &pdev->dev; |
| 1187 | info->edev->supported_cable = max77693_extcon_cable; | 1187 | |
| 1188 | ret = extcon_dev_register(info->edev); | 1188 | ret = devm_extcon_dev_register(&pdev->dev, info->edev); |
| 1189 | if (ret) { | 1189 | if (ret) { |
| 1190 | dev_err(&pdev->dev, "failed to register extcon device\n"); | 1190 | dev_err(&pdev->dev, "failed to register extcon device\n"); |
| 1191 | goto err_irq; | 1191 | goto err_irq; |
| 1192 | } | 1192 | } |
| 1193 | 1193 | ||
| 1194 | |||
| 1195 | /* Initialize MUIC register by using platform data or default data */ | 1194 | /* Initialize MUIC register by using platform data or default data */ |
| 1196 | if (pdata->muic_data) { | 1195 | if (pdata && pdata->muic_data) { |
| 1197 | init_data = pdata->muic_data->init_data; | 1196 | init_data = pdata->muic_data->init_data; |
| 1198 | num_init_data = pdata->muic_data->num_init_data; | 1197 | num_init_data = pdata->muic_data->num_init_data; |
| 1199 | } else { | 1198 | } else { |
| @@ -1226,7 +1225,7 @@ static int max77693_muic_probe(struct platform_device *pdev) | |||
| 1226 | = init_data[i].data; | 1225 | = init_data[i].data; |
| 1227 | } | 1226 | } |
| 1228 | 1227 | ||
| 1229 | if (pdata->muic_data) { | 1228 | if (pdata && pdata->muic_data) { |
| 1230 | struct max77693_muic_platform_data *muic_pdata | 1229 | struct max77693_muic_platform_data *muic_pdata |
| 1231 | = pdata->muic_data; | 1230 | = pdata->muic_data; |
| 1232 | 1231 | ||
| @@ -1267,7 +1266,7 @@ static int max77693_muic_probe(struct platform_device *pdev) | |||
| 1267 | MAX77693_MUIC_REG_ID, &id); | 1266 | MAX77693_MUIC_REG_ID, &id); |
| 1268 | if (ret < 0) { | 1267 | if (ret < 0) { |
| 1269 | dev_err(&pdev->dev, "failed to read revision number\n"); | 1268 | dev_err(&pdev->dev, "failed to read revision number\n"); |
| 1270 | goto err_extcon; | 1269 | goto err_irq; |
| 1271 | } | 1270 | } |
| 1272 | dev_info(info->dev, "device ID : 0x%x\n", id); | 1271 | dev_info(info->dev, "device ID : 0x%x\n", id); |
| 1273 | 1272 | ||
| @@ -1283,12 +1282,11 @@ static int max77693_muic_probe(struct platform_device *pdev) | |||
| 1283 | * driver should notify cable state to upper layer. | 1282 | * driver should notify cable state to upper layer. |
| 1284 | */ | 1283 | */ |
| 1285 | INIT_DELAYED_WORK(&info->wq_detcable, max77693_muic_detect_cable_wq); | 1284 | INIT_DELAYED_WORK(&info->wq_detcable, max77693_muic_detect_cable_wq); |
| 1286 | schedule_delayed_work(&info->wq_detcable, delay_jiffies); | 1285 | queue_delayed_work(system_power_efficient_wq, &info->wq_detcable, |
| 1286 | delay_jiffies); | ||
| 1287 | 1287 | ||
| 1288 | return ret; | 1288 | return ret; |
| 1289 | 1289 | ||
| 1290 | err_extcon: | ||
| 1291 | extcon_dev_unregister(info->edev); | ||
| 1292 | err_irq: | 1290 | err_irq: |
| 1293 | while (--i >= 0) | 1291 | while (--i >= 0) |
| 1294 | free_irq(muic_irqs[i].virq, info); | 1292 | free_irq(muic_irqs[i].virq, info); |
| @@ -1304,7 +1302,6 @@ static int max77693_muic_remove(struct platform_device *pdev) | |||
| 1304 | free_irq(muic_irqs[i].virq, info); | 1302 | free_irq(muic_irqs[i].virq, info); |
| 1305 | cancel_work_sync(&info->irq_work); | 1303 | cancel_work_sync(&info->irq_work); |
| 1306 | input_unregister_device(info->dock); | 1304 | input_unregister_device(info->dock); |
| 1307 | extcon_dev_unregister(info->edev); | ||
| 1308 | 1305 | ||
| 1309 | return 0; | 1306 | return 0; |
| 1310 | } | 1307 | } |
diff --git a/drivers/extcon/extcon-max8997.c b/drivers/extcon/extcon-max8997.c index 6a00464658c5..d9f7f1baaa03 100644 --- a/drivers/extcon/extcon-max8997.c +++ b/drivers/extcon/extcon-max8997.c | |||
| @@ -699,23 +699,22 @@ static int max8997_muic_probe(struct platform_device *pdev) | |||
| 699 | } | 699 | } |
| 700 | 700 | ||
| 701 | /* External connector */ | 701 | /* External connector */ |
| 702 | info->edev = devm_kzalloc(&pdev->dev, sizeof(struct extcon_dev), | 702 | info->edev = devm_extcon_dev_allocate(&pdev->dev, max8997_extcon_cable); |
| 703 | GFP_KERNEL); | 703 | if (IS_ERR(info->edev)) { |
| 704 | if (!info->edev) { | ||
| 705 | dev_err(&pdev->dev, "failed to allocate memory for extcon\n"); | 704 | dev_err(&pdev->dev, "failed to allocate memory for extcon\n"); |
| 706 | ret = -ENOMEM; | 705 | ret = -ENOMEM; |
| 707 | goto err_irq; | 706 | goto err_irq; |
| 708 | } | 707 | } |
| 709 | info->edev->name = DEV_NAME; | 708 | info->edev->name = DEV_NAME; |
| 710 | info->edev->dev.parent = &pdev->dev; | 709 | info->edev->dev.parent = &pdev->dev; |
| 711 | info->edev->supported_cable = max8997_extcon_cable; | 710 | |
| 712 | ret = extcon_dev_register(info->edev); | 711 | ret = devm_extcon_dev_register(&pdev->dev, info->edev); |
| 713 | if (ret) { | 712 | if (ret) { |
| 714 | dev_err(&pdev->dev, "failed to register extcon device\n"); | 713 | dev_err(&pdev->dev, "failed to register extcon device\n"); |
| 715 | goto err_irq; | 714 | goto err_irq; |
| 716 | } | 715 | } |
| 717 | 716 | ||
| 718 | if (pdata->muic_pdata) { | 717 | if (pdata && pdata->muic_pdata) { |
| 719 | struct max8997_muic_platform_data *muic_pdata | 718 | struct max8997_muic_platform_data *muic_pdata |
| 720 | = pdata->muic_pdata; | 719 | = pdata->muic_pdata; |
| 721 | 720 | ||
| @@ -770,7 +769,8 @@ static int max8997_muic_probe(struct platform_device *pdev) | |||
| 770 | * driver should notify cable state to upper layer. | 769 | * driver should notify cable state to upper layer. |
| 771 | */ | 770 | */ |
| 772 | INIT_DELAYED_WORK(&info->wq_detcable, max8997_muic_detect_cable_wq); | 771 | INIT_DELAYED_WORK(&info->wq_detcable, max8997_muic_detect_cable_wq); |
| 773 | schedule_delayed_work(&info->wq_detcable, delay_jiffies); | 772 | queue_delayed_work(system_power_efficient_wq, &info->wq_detcable, |
| 773 | delay_jiffies); | ||
| 774 | 774 | ||
| 775 | return 0; | 775 | return 0; |
| 776 | 776 | ||
| @@ -789,8 +789,6 @@ static int max8997_muic_remove(struct platform_device *pdev) | |||
| 789 | free_irq(muic_irqs[i].virq, info); | 789 | free_irq(muic_irqs[i].virq, info); |
| 790 | cancel_work_sync(&info->irq_work); | 790 | cancel_work_sync(&info->irq_work); |
| 791 | 791 | ||
| 792 | extcon_dev_unregister(info->edev); | ||
| 793 | |||
| 794 | return 0; | 792 | return 0; |
| 795 | } | 793 | } |
| 796 | 794 | ||
diff --git a/drivers/extcon/extcon-palmas.c b/drivers/extcon/extcon-palmas.c index ddff2b72f0a8..7417ce84eb2d 100644 --- a/drivers/extcon/extcon-palmas.c +++ b/drivers/extcon/extcon-palmas.c | |||
| @@ -23,6 +23,7 @@ | |||
| 23 | #include <linux/module.h> | 23 | #include <linux/module.h> |
| 24 | #include <linux/interrupt.h> | 24 | #include <linux/interrupt.h> |
| 25 | #include <linux/platform_device.h> | 25 | #include <linux/platform_device.h> |
| 26 | #include <linux/slab.h> | ||
| 26 | #include <linux/err.h> | 27 | #include <linux/err.h> |
| 27 | #include <linux/mfd/palmas.h> | 28 | #include <linux/mfd/palmas.h> |
| 28 | #include <linux/of.h> | 29 | #include <linux/of.h> |
| @@ -56,7 +57,7 @@ static irqreturn_t palmas_vbus_irq_handler(int irq, void *_palmas_usb) | |||
| 56 | if (vbus_line_state & PALMAS_INT3_LINE_STATE_VBUS) { | 57 | if (vbus_line_state & PALMAS_INT3_LINE_STATE_VBUS) { |
| 57 | if (palmas_usb->linkstat != PALMAS_USB_STATE_VBUS) { | 58 | if (palmas_usb->linkstat != PALMAS_USB_STATE_VBUS) { |
| 58 | palmas_usb->linkstat = PALMAS_USB_STATE_VBUS; | 59 | palmas_usb->linkstat = PALMAS_USB_STATE_VBUS; |
| 59 | extcon_set_cable_state(&palmas_usb->edev, "USB", true); | 60 | extcon_set_cable_state(palmas_usb->edev, "USB", true); |
| 60 | dev_info(palmas_usb->dev, "USB cable is attached\n"); | 61 | dev_info(palmas_usb->dev, "USB cable is attached\n"); |
| 61 | } else { | 62 | } else { |
| 62 | dev_dbg(palmas_usb->dev, | 63 | dev_dbg(palmas_usb->dev, |
| @@ -65,7 +66,7 @@ static irqreturn_t palmas_vbus_irq_handler(int irq, void *_palmas_usb) | |||
| 65 | } else if (!(vbus_line_state & PALMAS_INT3_LINE_STATE_VBUS)) { | 66 | } else if (!(vbus_line_state & PALMAS_INT3_LINE_STATE_VBUS)) { |
| 66 | if (palmas_usb->linkstat == PALMAS_USB_STATE_VBUS) { | 67 | if (palmas_usb->linkstat == PALMAS_USB_STATE_VBUS) { |
| 67 | palmas_usb->linkstat = PALMAS_USB_STATE_DISCONNECT; | 68 | palmas_usb->linkstat = PALMAS_USB_STATE_DISCONNECT; |
| 68 | extcon_set_cable_state(&palmas_usb->edev, "USB", false); | 69 | extcon_set_cable_state(palmas_usb->edev, "USB", false); |
| 69 | dev_info(palmas_usb->dev, "USB cable is detached\n"); | 70 | dev_info(palmas_usb->dev, "USB cable is detached\n"); |
| 70 | } else { | 71 | } else { |
| 71 | dev_dbg(palmas_usb->dev, | 72 | dev_dbg(palmas_usb->dev, |
| @@ -92,7 +93,7 @@ static irqreturn_t palmas_id_irq_handler(int irq, void *_palmas_usb) | |||
| 92 | PALMAS_USB_ID_INT_LATCH_CLR, | 93 | PALMAS_USB_ID_INT_LATCH_CLR, |
| 93 | PALMAS_USB_ID_INT_EN_HI_CLR_ID_GND); | 94 | PALMAS_USB_ID_INT_EN_HI_CLR_ID_GND); |
| 94 | palmas_usb->linkstat = PALMAS_USB_STATE_ID; | 95 | palmas_usb->linkstat = PALMAS_USB_STATE_ID; |
| 95 | extcon_set_cable_state(&palmas_usb->edev, "USB-HOST", true); | 96 | extcon_set_cable_state(palmas_usb->edev, "USB-HOST", true); |
| 96 | dev_info(palmas_usb->dev, "USB-HOST cable is attached\n"); | 97 | dev_info(palmas_usb->dev, "USB-HOST cable is attached\n"); |
| 97 | } else if ((set & PALMAS_USB_ID_INT_SRC_ID_FLOAT) && | 98 | } else if ((set & PALMAS_USB_ID_INT_SRC_ID_FLOAT) && |
| 98 | (id_src & PALMAS_USB_ID_INT_SRC_ID_FLOAT)) { | 99 | (id_src & PALMAS_USB_ID_INT_SRC_ID_FLOAT)) { |
| @@ -100,17 +101,17 @@ static irqreturn_t palmas_id_irq_handler(int irq, void *_palmas_usb) | |||
| 100 | PALMAS_USB_ID_INT_LATCH_CLR, | 101 | PALMAS_USB_ID_INT_LATCH_CLR, |
| 101 | PALMAS_USB_ID_INT_EN_HI_CLR_ID_FLOAT); | 102 | PALMAS_USB_ID_INT_EN_HI_CLR_ID_FLOAT); |
| 102 | palmas_usb->linkstat = PALMAS_USB_STATE_DISCONNECT; | 103 | palmas_usb->linkstat = PALMAS_USB_STATE_DISCONNECT; |
| 103 | extcon_set_cable_state(&palmas_usb->edev, "USB-HOST", false); | 104 | extcon_set_cable_state(palmas_usb->edev, "USB-HOST", false); |
| 104 | dev_info(palmas_usb->dev, "USB-HOST cable is detached\n"); | 105 | dev_info(palmas_usb->dev, "USB-HOST cable is detached\n"); |
| 105 | } else if ((palmas_usb->linkstat == PALMAS_USB_STATE_ID) && | 106 | } else if ((palmas_usb->linkstat == PALMAS_USB_STATE_ID) && |
| 106 | (!(set & PALMAS_USB_ID_INT_SRC_ID_GND))) { | 107 | (!(set & PALMAS_USB_ID_INT_SRC_ID_GND))) { |
| 107 | palmas_usb->linkstat = PALMAS_USB_STATE_DISCONNECT; | 108 | palmas_usb->linkstat = PALMAS_USB_STATE_DISCONNECT; |
| 108 | extcon_set_cable_state(&palmas_usb->edev, "USB-HOST", false); | 109 | extcon_set_cable_state(palmas_usb->edev, "USB-HOST", false); |
| 109 | dev_info(palmas_usb->dev, "USB-HOST cable is detached\n"); | 110 | dev_info(palmas_usb->dev, "USB-HOST cable is detached\n"); |
| 110 | } else if ((palmas_usb->linkstat == PALMAS_USB_STATE_DISCONNECT) && | 111 | } else if ((palmas_usb->linkstat == PALMAS_USB_STATE_DISCONNECT) && |
| 111 | (id_src & PALMAS_USB_ID_INT_SRC_ID_GND)) { | 112 | (id_src & PALMAS_USB_ID_INT_SRC_ID_GND)) { |
| 112 | palmas_usb->linkstat = PALMAS_USB_STATE_ID; | 113 | palmas_usb->linkstat = PALMAS_USB_STATE_ID; |
| 113 | extcon_set_cable_state(&palmas_usb->edev, "USB-HOST", true); | 114 | extcon_set_cable_state(palmas_usb->edev, "USB-HOST", true); |
| 114 | dev_info(palmas_usb->dev, " USB-HOST cable is attached\n"); | 115 | dev_info(palmas_usb->dev, " USB-HOST cable is attached\n"); |
| 115 | } | 116 | } |
| 116 | 117 | ||
| @@ -186,13 +187,20 @@ static int palmas_usb_probe(struct platform_device *pdev) | |||
| 186 | 187 | ||
| 187 | platform_set_drvdata(pdev, palmas_usb); | 188 | platform_set_drvdata(pdev, palmas_usb); |
| 188 | 189 | ||
| 189 | palmas_usb->edev.supported_cable = palmas_extcon_cable; | 190 | palmas_usb->edev = devm_extcon_dev_allocate(&pdev->dev, |
| 190 | palmas_usb->edev.dev.parent = palmas_usb->dev; | 191 | palmas_extcon_cable); |
| 191 | palmas_usb->edev.mutually_exclusive = mutually_exclusive; | 192 | if (IS_ERR(palmas_usb->edev)) { |
| 193 | dev_err(&pdev->dev, "failed to allocate extcon device\n"); | ||
| 194 | return -ENOMEM; | ||
| 195 | } | ||
| 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; | ||
| 192 | 199 | ||
| 193 | status = extcon_dev_register(&palmas_usb->edev); | 200 | status = devm_extcon_dev_register(&pdev->dev, palmas_usb->edev); |
| 194 | if (status) { | 201 | if (status) { |
| 195 | dev_err(&pdev->dev, "failed to register extcon device\n"); | 202 | dev_err(&pdev->dev, "failed to register extcon device\n"); |
| 203 | kfree(palmas_usb->edev->name); | ||
| 196 | return status; | 204 | return status; |
| 197 | } | 205 | } |
| 198 | 206 | ||
| @@ -206,7 +214,8 @@ static int palmas_usb_probe(struct platform_device *pdev) | |||
| 206 | if (status < 0) { | 214 | if (status < 0) { |
| 207 | dev_err(&pdev->dev, "can't get IRQ %d, err %d\n", | 215 | dev_err(&pdev->dev, "can't get IRQ %d, err %d\n", |
| 208 | palmas_usb->id_irq, status); | 216 | palmas_usb->id_irq, status); |
| 209 | goto fail_extcon; | 217 | kfree(palmas_usb->edev->name); |
| 218 | return status; | ||
| 210 | } | 219 | } |
| 211 | } | 220 | } |
| 212 | 221 | ||
| @@ -220,25 +229,21 @@ static int palmas_usb_probe(struct platform_device *pdev) | |||
| 220 | if (status < 0) { | 229 | if (status < 0) { |
| 221 | dev_err(&pdev->dev, "can't get IRQ %d, err %d\n", | 230 | dev_err(&pdev->dev, "can't get IRQ %d, err %d\n", |
| 222 | palmas_usb->vbus_irq, status); | 231 | palmas_usb->vbus_irq, status); |
| 223 | goto fail_extcon; | 232 | kfree(palmas_usb->edev->name); |
| 233 | return status; | ||
| 224 | } | 234 | } |
| 225 | } | 235 | } |
| 226 | 236 | ||
| 227 | palmas_enable_irq(palmas_usb); | 237 | palmas_enable_irq(palmas_usb); |
| 228 | device_set_wakeup_capable(&pdev->dev, true); | 238 | device_set_wakeup_capable(&pdev->dev, true); |
| 229 | return 0; | 239 | return 0; |
| 230 | |||
| 231 | fail_extcon: | ||
| 232 | extcon_dev_unregister(&palmas_usb->edev); | ||
| 233 | |||
| 234 | return status; | ||
| 235 | } | 240 | } |
| 236 | 241 | ||
| 237 | static int palmas_usb_remove(struct platform_device *pdev) | 242 | static int palmas_usb_remove(struct platform_device *pdev) |
| 238 | { | 243 | { |
| 239 | struct palmas_usb *palmas_usb = platform_get_drvdata(pdev); | 244 | struct palmas_usb *palmas_usb = platform_get_drvdata(pdev); |
| 240 | 245 | ||
| 241 | extcon_dev_unregister(&palmas_usb->edev); | 246 | kfree(palmas_usb->edev->name); |
| 242 | 247 | ||
| 243 | return 0; | 248 | return 0; |
| 244 | } | 249 | } |
