mirror of https://gitee.com/openkylin/linux.git
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 -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.11 (GNU/Linux) iQIcBAABAgAGBQJVzIaXAAoJEJzN3yze689T9AYP+wSjsZuqVetmuwchzCrhKBJf wLisDyBKyuZ1OdBS0114pFxjrT11ULGQv9kk1kLQgSCVbnKZvMrRdZkkg9lPA2ut y9PH/1atvB1lSDZaU73I6Hof+7GEt8U38Hk5Ter69xqvhwn2Txg449+HZvwva+RB yrAEDSxeOUPpCGwI/qd913q7918LvUgNvM1IIHHBuJE3NAfAqpec2Pxo1iJLBlac dHOSrxLfVo/xRKUghv3VcP3tzxpznN/xYqYf7t8Q4n0p4pV4FIscqOCMk0jjYISu jP/kdEurzAxqIi1qDIRIcbHGSLMyzlD2qk/uvB+i6Vjf/6N5aFXjTasC5SvbLeVq jZvuoOmtCG412FnwAZNusMf64R8JLWgEQoc9txtOqB4LORD3uObUB0+IKDQmWWW0 lySUFO4CZFhhxlSIQSwjESnxAuhxXSTWJIFn8ZJebmorvZgnnyO4mLo2FNuxT9yO nURvLZK2FbOo60EGYiwHvv4f7eOV7GuxYpUtunYBwjWmRE8yf5ofRFaHpmi9ynA8 y1IJKjyF7znPvwABl9wsthkK5Pt/pJTaVyfPDldJAveK5JjBFOHMp3QLmx74FSlw Z9TmJ/VIoFg6tZINT997lMpKerGBFU2TlNpJFCb0fRUurd9xNfMCjhIqhDyRvVhJ 6BOMAHTxLjH7eXYarEp8 =Cd4Z -----END PGP SIGNATURE----- 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
This commit is contained in:
commit
672cfeeb93
|
@ -10,8 +10,11 @@ Required Properties:
|
||||||
|
|
||||||
Optional Properties:
|
Optional Properties:
|
||||||
- ti,wakeup : To enable the wakeup comparator in probe
|
- ti,wakeup : To enable the wakeup comparator in probe
|
||||||
- ti,enable-id-detection: Perform ID detection.
|
- ti,enable-id-detection: Perform ID detection. If id-gpio is specified
|
||||||
|
it performs id-detection using GPIO else using OTG core.
|
||||||
- ti,enable-vbus-detection: Perform VBUS detection.
|
- ti,enable-vbus-detection: Perform VBUS detection.
|
||||||
|
- id-gpio: gpio for GPIO ID detection. See gpio binding.
|
||||||
|
- debounce-delay-ms: debounce delay for GPIO ID pin in milliseconds.
|
||||||
|
|
||||||
palmas-usb {
|
palmas-usb {
|
||||||
compatible = "ti,twl6035-usb", "ti,palmas-usb";
|
compatible = "ti,twl6035-usb", "ti,palmas-usb";
|
||||||
|
|
|
@ -20,10 +20,12 @@
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/interrupt.h>
|
#include <linux/interrupt.h>
|
||||||
#include <linux/err.h>
|
#include <linux/err.h>
|
||||||
|
#include <linux/gpio/consumer.h>
|
||||||
#include <linux/gpio.h>
|
#include <linux/gpio.h>
|
||||||
#include <linux/input.h>
|
#include <linux/input.h>
|
||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
#include <linux/pm_runtime.h>
|
#include <linux/pm_runtime.h>
|
||||||
|
#include <linux/property.h>
|
||||||
#include <linux/regulator/consumer.h>
|
#include <linux/regulator/consumer.h>
|
||||||
#include <linux/extcon.h>
|
#include <linux/extcon.h>
|
||||||
|
|
||||||
|
@ -46,6 +48,9 @@
|
||||||
#define HPDET_DEBOUNCE 500
|
#define HPDET_DEBOUNCE 500
|
||||||
#define DEFAULT_MICD_TIMEOUT 2000
|
#define DEFAULT_MICD_TIMEOUT 2000
|
||||||
|
|
||||||
|
#define MICD_DBTIME_TWO_READINGS 2
|
||||||
|
#define MICD_DBTIME_FOUR_READINGS 4
|
||||||
|
|
||||||
#define MICD_LVL_1_TO_7 (ARIZONA_MICD_LVL_1 | ARIZONA_MICD_LVL_2 | \
|
#define MICD_LVL_1_TO_7 (ARIZONA_MICD_LVL_1 | ARIZONA_MICD_LVL_2 | \
|
||||||
ARIZONA_MICD_LVL_3 | ARIZONA_MICD_LVL_4 | \
|
ARIZONA_MICD_LVL_3 | ARIZONA_MICD_LVL_4 | \
|
||||||
ARIZONA_MICD_LVL_5 | ARIZONA_MICD_LVL_6 | \
|
ARIZONA_MICD_LVL_5 | ARIZONA_MICD_LVL_6 | \
|
||||||
|
@ -94,6 +99,8 @@ struct arizona_extcon_info {
|
||||||
int hpdet_ip_version;
|
int hpdet_ip_version;
|
||||||
|
|
||||||
struct extcon_dev *edev;
|
struct extcon_dev *edev;
|
||||||
|
|
||||||
|
struct gpio_desc *micd_pol_gpio;
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct arizona_micd_config micd_default_modes[] = {
|
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)
|
||||||
if (arizona->pdata.micd_pol_gpio > 0)
|
if (arizona->pdata.micd_pol_gpio > 0)
|
||||||
gpio_set_value_cansleep(arizona->pdata.micd_pol_gpio,
|
gpio_set_value_cansleep(arizona->pdata.micd_pol_gpio,
|
||||||
info->micd_modes[mode].gpio);
|
info->micd_modes[mode].gpio);
|
||||||
|
else
|
||||||
|
gpiod_set_value_cansleep(info->micd_pol_gpio,
|
||||||
|
info->micd_modes[mode].gpio);
|
||||||
|
|
||||||
regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1,
|
regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1,
|
||||||
ARIZONA_MICD_BIAS_SRC_MASK,
|
ARIZONA_MICD_BIAS_SRC_MASK,
|
||||||
info->micd_modes[mode].bias <<
|
info->micd_modes[mode].bias <<
|
||||||
|
@ -757,10 +768,11 @@ static void arizona_micd_timeout_work(struct work_struct *work)
|
||||||
mutex_lock(&info->lock);
|
mutex_lock(&info->lock);
|
||||||
|
|
||||||
dev_dbg(info->arizona->dev, "MICD timed out, reporting HP\n");
|
dev_dbg(info->arizona->dev, "MICD timed out, reporting HP\n");
|
||||||
arizona_identify_headphone(info);
|
|
||||||
|
|
||||||
info->detecting = false;
|
info->detecting = false;
|
||||||
|
|
||||||
|
arizona_identify_headphone(info);
|
||||||
|
|
||||||
arizona_stop_mic(info);
|
arizona_stop_mic(info);
|
||||||
|
|
||||||
mutex_unlock(&info->lock);
|
mutex_unlock(&info->lock);
|
||||||
|
@ -820,12 +832,18 @@ static void arizona_micd_detect(struct work_struct *work)
|
||||||
/* Due to jack detect this should never happen */
|
/* Due to jack detect this should never happen */
|
||||||
if (!(val & ARIZONA_MICD_STS)) {
|
if (!(val & ARIZONA_MICD_STS)) {
|
||||||
dev_warn(arizona->dev, "Detected open circuit\n");
|
dev_warn(arizona->dev, "Detected open circuit\n");
|
||||||
|
info->mic = false;
|
||||||
|
arizona_stop_mic(info);
|
||||||
info->detecting = false;
|
info->detecting = false;
|
||||||
|
arizona_identify_headphone(info);
|
||||||
goto handled;
|
goto handled;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If we got a high impedence we should have a headset, report it. */
|
/* If we got a high impedence we should have a headset, report it. */
|
||||||
if (info->detecting && (val & ARIZONA_MICD_LVL_8)) {
|
if (info->detecting && (val & ARIZONA_MICD_LVL_8)) {
|
||||||
|
info->mic = true;
|
||||||
|
info->detecting = false;
|
||||||
|
|
||||||
arizona_identify_headphone(info);
|
arizona_identify_headphone(info);
|
||||||
|
|
||||||
ret = extcon_set_cable_state_(info->edev,
|
ret = extcon_set_cable_state_(info->edev,
|
||||||
|
@ -841,8 +859,6 @@ static void arizona_micd_detect(struct work_struct *work)
|
||||||
ret);
|
ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
info->mic = true;
|
|
||||||
info->detecting = false;
|
|
||||||
goto handled;
|
goto handled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -855,10 +871,11 @@ static void arizona_micd_detect(struct work_struct *work)
|
||||||
if (info->detecting && (val & MICD_LVL_1_TO_7)) {
|
if (info->detecting && (val & MICD_LVL_1_TO_7)) {
|
||||||
if (info->jack_flips >= info->micd_num_modes * 10) {
|
if (info->jack_flips >= info->micd_num_modes * 10) {
|
||||||
dev_dbg(arizona->dev, "Detected HP/line\n");
|
dev_dbg(arizona->dev, "Detected HP/line\n");
|
||||||
arizona_identify_headphone(info);
|
|
||||||
|
|
||||||
info->detecting = false;
|
info->detecting = false;
|
||||||
|
|
||||||
|
arizona_identify_headphone(info);
|
||||||
|
|
||||||
arizona_stop_mic(info);
|
arizona_stop_mic(info);
|
||||||
} else {
|
} else {
|
||||||
info->micd_mode++;
|
info->micd_mode++;
|
||||||
|
@ -1110,12 +1127,12 @@ static void arizona_micd_set_level(struct arizona *arizona, int index,
|
||||||
regmap_update_bits(arizona->regmap, reg, mask, level);
|
regmap_update_bits(arizona->regmap, reg, mask, level);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int arizona_extcon_of_get_pdata(struct arizona *arizona)
|
static int arizona_extcon_device_get_pdata(struct arizona *arizona)
|
||||||
{
|
{
|
||||||
struct arizona_pdata *pdata = &arizona->pdata;
|
struct arizona_pdata *pdata = &arizona->pdata;
|
||||||
unsigned int val = ARIZONA_ACCDET_MODE_HPL;
|
unsigned int val = ARIZONA_ACCDET_MODE_HPL;
|
||||||
|
|
||||||
of_property_read_u32(arizona->dev->of_node, "wlf,hpdet-channel", &val);
|
device_property_read_u32(arizona->dev, "wlf,hpdet-channel", &val);
|
||||||
switch (val) {
|
switch (val) {
|
||||||
case ARIZONA_ACCDET_MODE_HPL:
|
case ARIZONA_ACCDET_MODE_HPL:
|
||||||
case ARIZONA_ACCDET_MODE_HPR:
|
case ARIZONA_ACCDET_MODE_HPR:
|
||||||
|
@ -1127,6 +1144,24 @@ static int arizona_extcon_of_get_pdata(struct arizona *arizona)
|
||||||
pdata->hpdet_channel = ARIZONA_ACCDET_MODE_HPL;
|
pdata->hpdet_channel = ARIZONA_ACCDET_MODE_HPL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
device_property_read_u32(arizona->dev, "wlf,micd-detect-debounce",
|
||||||
|
&pdata->micd_detect_debounce);
|
||||||
|
|
||||||
|
device_property_read_u32(arizona->dev, "wlf,micd-bias-start-time",
|
||||||
|
&pdata->micd_bias_start_time);
|
||||||
|
|
||||||
|
device_property_read_u32(arizona->dev, "wlf,micd-rate",
|
||||||
|
&pdata->micd_rate);
|
||||||
|
|
||||||
|
device_property_read_u32(arizona->dev, "wlf,micd-dbtime",
|
||||||
|
&pdata->micd_dbtime);
|
||||||
|
|
||||||
|
device_property_read_u32(arizona->dev, "wlf,micd-timeout",
|
||||||
|
&pdata->micd_timeout);
|
||||||
|
|
||||||
|
pdata->micd_force_micbias = device_property_read_bool(arizona->dev,
|
||||||
|
"wlf,micd-force-micbias");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1147,10 +1182,8 @@ static int arizona_extcon_probe(struct platform_device *pdev)
|
||||||
if (!info)
|
if (!info)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
if (IS_ENABLED(CONFIG_OF)) {
|
if (!dev_get_platdata(arizona->dev))
|
||||||
if (!dev_get_platdata(arizona->dev))
|
arizona_extcon_device_get_pdata(arizona);
|
||||||
arizona_extcon_of_get_pdata(arizona);
|
|
||||||
}
|
|
||||||
|
|
||||||
info->micvdd = devm_regulator_get(&pdev->dev, "MICVDD");
|
info->micvdd = devm_regulator_get(&pdev->dev, "MICVDD");
|
||||||
if (IS_ERR(info->micvdd)) {
|
if (IS_ERR(info->micvdd)) {
|
||||||
|
@ -1241,6 +1274,27 @@ static int arizona_extcon_probe(struct platform_device *pdev)
|
||||||
arizona->pdata.micd_pol_gpio, ret);
|
arizona->pdata.micd_pol_gpio, ret);
|
||||||
goto err_register;
|
goto err_register;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
if (info->micd_modes[0].gpio)
|
||||||
|
mode = GPIOD_OUT_HIGH;
|
||||||
|
else
|
||||||
|
mode = GPIOD_OUT_LOW;
|
||||||
|
|
||||||
|
/* We can't use devm here because we need to do the get
|
||||||
|
* against the MFD device, as that is where the of_node
|
||||||
|
* will reside, but if we devm against that the GPIO
|
||||||
|
* will not be freed if the extcon driver is unloaded.
|
||||||
|
*/
|
||||||
|
info->micd_pol_gpio = gpiod_get_optional(arizona->dev,
|
||||||
|
"wlf,micd-pol",
|
||||||
|
GPIOD_OUT_LOW);
|
||||||
|
if (IS_ERR(info->micd_pol_gpio)) {
|
||||||
|
ret = PTR_ERR(info->micd_pol_gpio);
|
||||||
|
dev_err(arizona->dev,
|
||||||
|
"Failed to get microphone polarity GPIO: %d\n",
|
||||||
|
ret);
|
||||||
|
goto err_register;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (arizona->pdata.hpdet_id_gpio > 0) {
|
if (arizona->pdata.hpdet_id_gpio > 0) {
|
||||||
|
@ -1251,7 +1305,7 @@ static int arizona_extcon_probe(struct platform_device *pdev)
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
dev_err(arizona->dev, "Failed to request GPIO%d: %d\n",
|
dev_err(arizona->dev, "Failed to request GPIO%d: %d\n",
|
||||||
arizona->pdata.hpdet_id_gpio, ret);
|
arizona->pdata.hpdet_id_gpio, ret);
|
||||||
goto err_register;
|
goto err_gpio;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1267,11 +1321,19 @@ static int arizona_extcon_probe(struct platform_device *pdev)
|
||||||
arizona->pdata.micd_rate
|
arizona->pdata.micd_rate
|
||||||
<< ARIZONA_MICD_RATE_SHIFT);
|
<< ARIZONA_MICD_RATE_SHIFT);
|
||||||
|
|
||||||
if (arizona->pdata.micd_dbtime)
|
switch (arizona->pdata.micd_dbtime) {
|
||||||
|
case MICD_DBTIME_FOUR_READINGS:
|
||||||
regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1,
|
regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1,
|
||||||
ARIZONA_MICD_DBTIME_MASK,
|
ARIZONA_MICD_DBTIME_MASK,
|
||||||
arizona->pdata.micd_dbtime
|
ARIZONA_MICD_DBTIME);
|
||||||
<< ARIZONA_MICD_DBTIME_SHIFT);
|
break;
|
||||||
|
case MICD_DBTIME_TWO_READINGS:
|
||||||
|
regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1,
|
||||||
|
ARIZONA_MICD_DBTIME_MASK, 0);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
BUILD_BUG_ON(ARRAY_SIZE(arizona_micd_levels) != 0x40);
|
BUILD_BUG_ON(ARRAY_SIZE(arizona_micd_levels) != 0x40);
|
||||||
|
|
||||||
|
@ -1295,7 +1357,7 @@ static int arizona_extcon_probe(struct platform_device *pdev)
|
||||||
dev_err(arizona->dev,
|
dev_err(arizona->dev,
|
||||||
"MICD ranges must be sorted\n");
|
"MICD ranges must be sorted\n");
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto err_input;
|
goto err_gpio;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1314,7 +1376,7 @@ static int arizona_extcon_probe(struct platform_device *pdev)
|
||||||
dev_err(arizona->dev, "Unsupported MICD level %d\n",
|
dev_err(arizona->dev, "Unsupported MICD level %d\n",
|
||||||
info->micd_ranges[i].max);
|
info->micd_ranges[i].max);
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto err_input;
|
goto err_gpio;
|
||||||
}
|
}
|
||||||
|
|
||||||
dev_dbg(arizona->dev, "%d ohms for MICD threshold %d\n",
|
dev_dbg(arizona->dev, "%d ohms for MICD threshold %d\n",
|
||||||
|
@ -1387,7 +1449,7 @@ static int arizona_extcon_probe(struct platform_device *pdev)
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
dev_err(&pdev->dev, "Failed to get JACKDET rise IRQ: %d\n",
|
dev_err(&pdev->dev, "Failed to get JACKDET rise IRQ: %d\n",
|
||||||
ret);
|
ret);
|
||||||
goto err_input;
|
goto err_gpio;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = arizona_set_irq_wake(arizona, jack_irq_rise, 1);
|
ret = arizona_set_irq_wake(arizona, jack_irq_rise, 1);
|
||||||
|
@ -1458,7 +1520,8 @@ static int arizona_extcon_probe(struct platform_device *pdev)
|
||||||
arizona_set_irq_wake(arizona, jack_irq_rise, 0);
|
arizona_set_irq_wake(arizona, jack_irq_rise, 0);
|
||||||
err_rise:
|
err_rise:
|
||||||
arizona_free_irq(arizona, jack_irq_rise, info);
|
arizona_free_irq(arizona, jack_irq_rise, info);
|
||||||
err_input:
|
err_gpio:
|
||||||
|
gpiod_put(info->micd_pol_gpio);
|
||||||
err_register:
|
err_register:
|
||||||
pm_runtime_disable(&pdev->dev);
|
pm_runtime_disable(&pdev->dev);
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -1470,6 +1533,8 @@ static int arizona_extcon_remove(struct platform_device *pdev)
|
||||||
struct arizona *arizona = info->arizona;
|
struct arizona *arizona = info->arizona;
|
||||||
int jack_irq_rise, jack_irq_fall;
|
int jack_irq_rise, jack_irq_fall;
|
||||||
|
|
||||||
|
gpiod_put(info->micd_pol_gpio);
|
||||||
|
|
||||||
pm_runtime_disable(&pdev->dev);
|
pm_runtime_disable(&pdev->dev);
|
||||||
|
|
||||||
regmap_update_bits(arizona->regmap,
|
regmap_update_bits(arizona->regmap,
|
||||||
|
|
|
@ -65,22 +65,6 @@ static irqreturn_t gpio_irq_handler(int irq, void *dev_id)
|
||||||
return IRQ_HANDLED;
|
return IRQ_HANDLED;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t extcon_gpio_print_state(struct extcon_dev *edev, char *buf)
|
|
||||||
{
|
|
||||||
struct device *dev = edev->dev.parent;
|
|
||||||
struct gpio_extcon_data *extcon_data = dev_get_drvdata(dev);
|
|
||||||
const char *state;
|
|
||||||
|
|
||||||
if (extcon_get_state(edev))
|
|
||||||
state = extcon_data->state_on;
|
|
||||||
else
|
|
||||||
state = extcon_data->state_off;
|
|
||||||
|
|
||||||
if (state)
|
|
||||||
return sprintf(buf, "%s\n", state);
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int gpio_extcon_probe(struct platform_device *pdev)
|
static int gpio_extcon_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct gpio_extcon_platform_data *pdata = dev_get_platdata(&pdev->dev);
|
struct gpio_extcon_platform_data *pdata = dev_get_platdata(&pdev->dev);
|
||||||
|
@ -110,8 +94,6 @@ static int gpio_extcon_probe(struct platform_device *pdev)
|
||||||
extcon_data->state_on = pdata->state_on;
|
extcon_data->state_on = pdata->state_on;
|
||||||
extcon_data->state_off = pdata->state_off;
|
extcon_data->state_off = pdata->state_off;
|
||||||
extcon_data->check_on_resume = pdata->check_on_resume;
|
extcon_data->check_on_resume = pdata->check_on_resume;
|
||||||
if (pdata->state_on && pdata->state_off)
|
|
||||||
extcon_data->edev->print_state = extcon_gpio_print_state;
|
|
||||||
|
|
||||||
ret = devm_gpio_request_one(&pdev->dev, extcon_data->gpio, GPIOF_DIR_IN,
|
ret = devm_gpio_request_one(&pdev->dev, extcon_data->gpio, GPIOF_DIR_IN,
|
||||||
pdev->name);
|
pdev->name);
|
||||||
|
|
|
@ -781,6 +781,15 @@ static int max77843_muic_probe(struct platform_device *pdev)
|
||||||
/* Support virtual irq domain for max77843 MUIC device */
|
/* Support virtual irq domain for max77843 MUIC device */
|
||||||
INIT_WORK(&info->irq_work, max77843_muic_irq_work);
|
INIT_WORK(&info->irq_work, max77843_muic_irq_work);
|
||||||
|
|
||||||
|
/* Clear IRQ bits before request IRQs */
|
||||||
|
ret = regmap_bulk_read(max77843->regmap_muic,
|
||||||
|
MAX77843_MUIC_REG_INT1, info->status,
|
||||||
|
MAX77843_MUIC_IRQ_NUM);
|
||||||
|
if (ret) {
|
||||||
|
dev_err(&pdev->dev, "Failed to Clear IRQ bits\n");
|
||||||
|
goto err_muic_irq;
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_SIZE(max77843_muic_irqs); i++) {
|
for (i = 0; i < ARRAY_SIZE(max77843_muic_irqs); i++) {
|
||||||
struct max77843_muic_irq *muic_irq = &max77843_muic_irqs[i];
|
struct max77843_muic_irq *muic_irq = &max77843_muic_irqs[i];
|
||||||
unsigned int virq = 0;
|
unsigned int virq = 0;
|
||||||
|
|
|
@ -28,6 +28,11 @@
|
||||||
#include <linux/mfd/palmas.h>
|
#include <linux/mfd/palmas.h>
|
||||||
#include <linux/of.h>
|
#include <linux/of.h>
|
||||||
#include <linux/of_platform.h>
|
#include <linux/of_platform.h>
|
||||||
|
#include <linux/of_gpio.h>
|
||||||
|
#include <linux/gpio/consumer.h>
|
||||||
|
#include <linux/workqueue.h>
|
||||||
|
|
||||||
|
#define USB_GPIO_DEBOUNCE_MS 20 /* ms */
|
||||||
|
|
||||||
static const unsigned int palmas_extcon_cable[] = {
|
static const unsigned int palmas_extcon_cable[] = {
|
||||||
EXTCON_USB,
|
EXTCON_USB,
|
||||||
|
@ -35,8 +40,6 @@ static const unsigned int palmas_extcon_cable[] = {
|
||||||
EXTCON_NONE,
|
EXTCON_NONE,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const int mutually_exclusive[] = {0x3, 0x0};
|
|
||||||
|
|
||||||
static void palmas_usb_wakeup(struct palmas *palmas, int enable)
|
static void palmas_usb_wakeup(struct palmas *palmas, int enable)
|
||||||
{
|
{
|
||||||
if (enable)
|
if (enable)
|
||||||
|
@ -120,19 +123,54 @@ static irqreturn_t palmas_id_irq_handler(int irq, void *_palmas_usb)
|
||||||
return IRQ_HANDLED;
|
return IRQ_HANDLED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void palmas_gpio_id_detect(struct work_struct *work)
|
||||||
|
{
|
||||||
|
int id;
|
||||||
|
struct palmas_usb *palmas_usb = container_of(to_delayed_work(work),
|
||||||
|
struct palmas_usb,
|
||||||
|
wq_detectid);
|
||||||
|
struct extcon_dev *edev = palmas_usb->edev;
|
||||||
|
|
||||||
|
if (!palmas_usb->id_gpiod)
|
||||||
|
return;
|
||||||
|
|
||||||
|
id = gpiod_get_value_cansleep(palmas_usb->id_gpiod);
|
||||||
|
|
||||||
|
if (id) {
|
||||||
|
extcon_set_cable_state_(edev, EXTCON_USB_HOST, false);
|
||||||
|
dev_info(palmas_usb->dev, "USB-HOST cable is detached\n");
|
||||||
|
} else {
|
||||||
|
extcon_set_cable_state_(edev, EXTCON_USB_HOST, true);
|
||||||
|
dev_info(palmas_usb->dev, "USB-HOST cable is attached\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static irqreturn_t palmas_gpio_id_irq_handler(int irq, void *_palmas_usb)
|
||||||
|
{
|
||||||
|
struct palmas_usb *palmas_usb = _palmas_usb;
|
||||||
|
|
||||||
|
queue_delayed_work(system_power_efficient_wq, &palmas_usb->wq_detectid,
|
||||||
|
palmas_usb->sw_debounce_jiffies);
|
||||||
|
|
||||||
|
return IRQ_HANDLED;
|
||||||
|
}
|
||||||
|
|
||||||
static void palmas_enable_irq(struct palmas_usb *palmas_usb)
|
static void palmas_enable_irq(struct palmas_usb *palmas_usb)
|
||||||
{
|
{
|
||||||
palmas_write(palmas_usb->palmas, PALMAS_USB_OTG_BASE,
|
palmas_write(palmas_usb->palmas, PALMAS_USB_OTG_BASE,
|
||||||
PALMAS_USB_VBUS_CTRL_SET,
|
PALMAS_USB_VBUS_CTRL_SET,
|
||||||
PALMAS_USB_VBUS_CTRL_SET_VBUS_ACT_COMP);
|
PALMAS_USB_VBUS_CTRL_SET_VBUS_ACT_COMP);
|
||||||
|
|
||||||
palmas_write(palmas_usb->palmas, PALMAS_USB_OTG_BASE,
|
if (palmas_usb->enable_id_detection) {
|
||||||
PALMAS_USB_ID_CTRL_SET, PALMAS_USB_ID_CTRL_SET_ID_ACT_COMP);
|
palmas_write(palmas_usb->palmas, PALMAS_USB_OTG_BASE,
|
||||||
|
PALMAS_USB_ID_CTRL_SET,
|
||||||
|
PALMAS_USB_ID_CTRL_SET_ID_ACT_COMP);
|
||||||
|
|
||||||
palmas_write(palmas_usb->palmas, PALMAS_USB_OTG_BASE,
|
palmas_write(palmas_usb->palmas, PALMAS_USB_OTG_BASE,
|
||||||
PALMAS_USB_ID_INT_EN_HI_SET,
|
PALMAS_USB_ID_INT_EN_HI_SET,
|
||||||
PALMAS_USB_ID_INT_EN_HI_SET_ID_GND |
|
PALMAS_USB_ID_INT_EN_HI_SET_ID_GND |
|
||||||
PALMAS_USB_ID_INT_EN_HI_SET_ID_FLOAT);
|
PALMAS_USB_ID_INT_EN_HI_SET_ID_FLOAT);
|
||||||
|
}
|
||||||
|
|
||||||
if (palmas_usb->enable_vbus_detection)
|
if (palmas_usb->enable_vbus_detection)
|
||||||
palmas_vbus_irq_handler(palmas_usb->vbus_irq, palmas_usb);
|
palmas_vbus_irq_handler(palmas_usb->vbus_irq, palmas_usb);
|
||||||
|
@ -171,20 +209,37 @@ static int palmas_usb_probe(struct platform_device *pdev)
|
||||||
palmas_usb->wakeup = pdata->wakeup;
|
palmas_usb->wakeup = pdata->wakeup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
palmas_usb->id_gpiod = devm_gpiod_get_optional(&pdev->dev, "id",
|
||||||
|
GPIOD_IN);
|
||||||
|
if (IS_ERR(palmas_usb->id_gpiod)) {
|
||||||
|
dev_err(&pdev->dev, "failed to get id gpio\n");
|
||||||
|
return PTR_ERR(palmas_usb->id_gpiod);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (palmas_usb->enable_id_detection && palmas_usb->id_gpiod) {
|
||||||
|
palmas_usb->enable_id_detection = false;
|
||||||
|
palmas_usb->enable_gpio_id_detection = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (palmas_usb->enable_gpio_id_detection) {
|
||||||
|
u32 debounce;
|
||||||
|
|
||||||
|
if (of_property_read_u32(node, "debounce-delay-ms", &debounce))
|
||||||
|
debounce = USB_GPIO_DEBOUNCE_MS;
|
||||||
|
|
||||||
|
status = gpiod_set_debounce(palmas_usb->id_gpiod,
|
||||||
|
debounce * 1000);
|
||||||
|
if (status < 0)
|
||||||
|
palmas_usb->sw_debounce_jiffies = msecs_to_jiffies(debounce);
|
||||||
|
}
|
||||||
|
|
||||||
|
INIT_DELAYED_WORK(&palmas_usb->wq_detectid, palmas_gpio_id_detect);
|
||||||
|
|
||||||
palmas->usb = palmas_usb;
|
palmas->usb = palmas_usb;
|
||||||
palmas_usb->palmas = palmas;
|
palmas_usb->palmas = palmas;
|
||||||
|
|
||||||
palmas_usb->dev = &pdev->dev;
|
palmas_usb->dev = &pdev->dev;
|
||||||
|
|
||||||
palmas_usb->id_otg_irq = regmap_irq_get_virq(palmas->irq_data,
|
|
||||||
PALMAS_ID_OTG_IRQ);
|
|
||||||
palmas_usb->id_irq = regmap_irq_get_virq(palmas->irq_data,
|
|
||||||
PALMAS_ID_IRQ);
|
|
||||||
palmas_usb->vbus_otg_irq = regmap_irq_get_virq(palmas->irq_data,
|
|
||||||
PALMAS_VBUS_OTG_IRQ);
|
|
||||||
palmas_usb->vbus_irq = regmap_irq_get_virq(palmas->irq_data,
|
|
||||||
PALMAS_VBUS_IRQ);
|
|
||||||
|
|
||||||
palmas_usb_wakeup(palmas, palmas_usb->wakeup);
|
palmas_usb_wakeup(palmas, palmas_usb->wakeup);
|
||||||
|
|
||||||
platform_set_drvdata(pdev, palmas_usb);
|
platform_set_drvdata(pdev, palmas_usb);
|
||||||
|
@ -195,7 +250,6 @@ static int palmas_usb_probe(struct platform_device *pdev)
|
||||||
dev_err(&pdev->dev, "failed to allocate extcon device\n");
|
dev_err(&pdev->dev, "failed to allocate extcon device\n");
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
palmas_usb->edev->mutually_exclusive = mutually_exclusive;
|
|
||||||
|
|
||||||
status = devm_extcon_dev_register(&pdev->dev, palmas_usb->edev);
|
status = devm_extcon_dev_register(&pdev->dev, palmas_usb->edev);
|
||||||
if (status) {
|
if (status) {
|
||||||
|
@ -204,6 +258,10 @@ static int palmas_usb_probe(struct platform_device *pdev)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (palmas_usb->enable_id_detection) {
|
if (palmas_usb->enable_id_detection) {
|
||||||
|
palmas_usb->id_otg_irq = regmap_irq_get_virq(palmas->irq_data,
|
||||||
|
PALMAS_ID_OTG_IRQ);
|
||||||
|
palmas_usb->id_irq = regmap_irq_get_virq(palmas->irq_data,
|
||||||
|
PALMAS_ID_IRQ);
|
||||||
status = devm_request_threaded_irq(palmas_usb->dev,
|
status = devm_request_threaded_irq(palmas_usb->dev,
|
||||||
palmas_usb->id_irq,
|
palmas_usb->id_irq,
|
||||||
NULL, palmas_id_irq_handler,
|
NULL, palmas_id_irq_handler,
|
||||||
|
@ -215,9 +273,33 @@ static int palmas_usb_probe(struct platform_device *pdev)
|
||||||
palmas_usb->id_irq, status);
|
palmas_usb->id_irq, status);
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
} else if (palmas_usb->enable_gpio_id_detection) {
|
||||||
|
palmas_usb->gpio_id_irq = gpiod_to_irq(palmas_usb->id_gpiod);
|
||||||
|
if (palmas_usb->gpio_id_irq < 0) {
|
||||||
|
dev_err(&pdev->dev, "failed to get id irq\n");
|
||||||
|
return palmas_usb->gpio_id_irq;
|
||||||
|
}
|
||||||
|
status = devm_request_threaded_irq(&pdev->dev,
|
||||||
|
palmas_usb->gpio_id_irq,
|
||||||
|
NULL,
|
||||||
|
palmas_gpio_id_irq_handler,
|
||||||
|
IRQF_TRIGGER_RISING |
|
||||||
|
IRQF_TRIGGER_FALLING |
|
||||||
|
IRQF_ONESHOT,
|
||||||
|
"palmas_usb_id",
|
||||||
|
palmas_usb);
|
||||||
|
if (status < 0) {
|
||||||
|
dev_err(&pdev->dev,
|
||||||
|
"failed to request handler for id irq\n");
|
||||||
|
return status;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (palmas_usb->enable_vbus_detection) {
|
if (palmas_usb->enable_vbus_detection) {
|
||||||
|
palmas_usb->vbus_otg_irq = regmap_irq_get_virq(palmas->irq_data,
|
||||||
|
PALMAS_VBUS_OTG_IRQ);
|
||||||
|
palmas_usb->vbus_irq = regmap_irq_get_virq(palmas->irq_data,
|
||||||
|
PALMAS_VBUS_IRQ);
|
||||||
status = devm_request_threaded_irq(palmas_usb->dev,
|
status = devm_request_threaded_irq(palmas_usb->dev,
|
||||||
palmas_usb->vbus_irq, NULL,
|
palmas_usb->vbus_irq, NULL,
|
||||||
palmas_vbus_irq_handler,
|
palmas_vbus_irq_handler,
|
||||||
|
@ -232,10 +314,21 @@ static int palmas_usb_probe(struct platform_device *pdev)
|
||||||
}
|
}
|
||||||
|
|
||||||
palmas_enable_irq(palmas_usb);
|
palmas_enable_irq(palmas_usb);
|
||||||
|
/* perform initial detection */
|
||||||
|
palmas_gpio_id_detect(&palmas_usb->wq_detectid.work);
|
||||||
device_set_wakeup_capable(&pdev->dev, true);
|
device_set_wakeup_capable(&pdev->dev, true);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int palmas_usb_remove(struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
struct palmas_usb *palmas_usb = platform_get_drvdata(pdev);
|
||||||
|
|
||||||
|
cancel_delayed_work_sync(&palmas_usb->wq_detectid);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_PM_SLEEP
|
#ifdef CONFIG_PM_SLEEP
|
||||||
static int palmas_usb_suspend(struct device *dev)
|
static int palmas_usb_suspend(struct device *dev)
|
||||||
{
|
{
|
||||||
|
@ -246,6 +339,8 @@ static int palmas_usb_suspend(struct device *dev)
|
||||||
enable_irq_wake(palmas_usb->vbus_irq);
|
enable_irq_wake(palmas_usb->vbus_irq);
|
||||||
if (palmas_usb->enable_id_detection)
|
if (palmas_usb->enable_id_detection)
|
||||||
enable_irq_wake(palmas_usb->id_irq);
|
enable_irq_wake(palmas_usb->id_irq);
|
||||||
|
if (palmas_usb->enable_gpio_id_detection)
|
||||||
|
enable_irq_wake(palmas_usb->gpio_id_irq);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -259,6 +354,8 @@ static int palmas_usb_resume(struct device *dev)
|
||||||
disable_irq_wake(palmas_usb->vbus_irq);
|
disable_irq_wake(palmas_usb->vbus_irq);
|
||||||
if (palmas_usb->enable_id_detection)
|
if (palmas_usb->enable_id_detection)
|
||||||
disable_irq_wake(palmas_usb->id_irq);
|
disable_irq_wake(palmas_usb->id_irq);
|
||||||
|
if (palmas_usb->enable_gpio_id_detection)
|
||||||
|
disable_irq_wake(palmas_usb->gpio_id_irq);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
};
|
};
|
||||||
|
@ -276,6 +373,7 @@ static const struct of_device_id of_palmas_match_tbl[] = {
|
||||||
|
|
||||||
static struct platform_driver palmas_usb_driver = {
|
static struct platform_driver palmas_usb_driver = {
|
||||||
.probe = palmas_usb_probe,
|
.probe = palmas_usb_probe,
|
||||||
|
.remove = palmas_usb_remove,
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = "palmas-usb",
|
.name = "palmas-usb",
|
||||||
.of_match_table = of_palmas_match_tbl,
|
.of_match_table = of_palmas_match_tbl,
|
||||||
|
|
|
@ -693,7 +693,6 @@ MODULE_DEVICE_TABLE(i2c, rt8973a_i2c_id);
|
||||||
static struct i2c_driver rt8973a_muic_i2c_driver = {
|
static struct i2c_driver rt8973a_muic_i2c_driver = {
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = "rt8973a",
|
.name = "rt8973a",
|
||||||
.owner = THIS_MODULE,
|
|
||||||
.pm = &rt8973a_muic_pm_ops,
|
.pm = &rt8973a_muic_pm_ops,
|
||||||
.of_match_table = rt8973a_dt_match,
|
.of_match_table = rt8973a_dt_match,
|
||||||
},
|
},
|
||||||
|
|
|
@ -685,7 +685,6 @@ MODULE_DEVICE_TABLE(i2c, sm5502_i2c_id);
|
||||||
static struct i2c_driver sm5502_muic_i2c_driver = {
|
static struct i2c_driver sm5502_muic_i2c_driver = {
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = "sm5502",
|
.name = "sm5502",
|
||||||
.owner = THIS_MODULE,
|
|
||||||
.pm = &sm5502_muic_pm_ops,
|
.pm = &sm5502_muic_pm_ops,
|
||||||
.of_match_table = sm5502_dt_match,
|
.of_match_table = sm5502_dt_match,
|
||||||
},
|
},
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/extcon.h>
|
#include <linux/extcon.h>
|
||||||
|
#include <linux/gpio.h>
|
||||||
#include <linux/gpio/consumer.h>
|
#include <linux/gpio/consumer.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/interrupt.h>
|
#include <linux/interrupt.h>
|
||||||
|
|
|
@ -126,7 +126,7 @@ static int find_cable_index_by_id(struct extcon_dev *edev, const unsigned int id
|
||||||
|
|
||||||
static int find_cable_id_by_name(struct extcon_dev *edev, const char *name)
|
static int find_cable_id_by_name(struct extcon_dev *edev, const char *name)
|
||||||
{
|
{
|
||||||
unsigned int id = -EINVAL;
|
int id = -EINVAL;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
/* Find the id of extcon cable */
|
/* Find the id of extcon cable */
|
||||||
|
@ -143,7 +143,7 @@ static int find_cable_id_by_name(struct extcon_dev *edev, const char *name)
|
||||||
|
|
||||||
static int find_cable_index_by_name(struct extcon_dev *edev, const char *name)
|
static int find_cable_index_by_name(struct extcon_dev *edev, const char *name)
|
||||||
{
|
{
|
||||||
unsigned int id;
|
int id;
|
||||||
|
|
||||||
if (edev->max_supported == 0)
|
if (edev->max_supported == 0)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@ -172,14 +172,6 @@ static ssize_t state_show(struct device *dev, struct device_attribute *attr,
|
||||||
int i, count = 0;
|
int i, count = 0;
|
||||||
struct extcon_dev *edev = dev_get_drvdata(dev);
|
struct extcon_dev *edev = dev_get_drvdata(dev);
|
||||||
|
|
||||||
if (edev->print_state) {
|
|
||||||
int ret = edev->print_state(edev, buf);
|
|
||||||
|
|
||||||
if (ret >= 0)
|
|
||||||
return ret;
|
|
||||||
/* Use default if failed */
|
|
||||||
}
|
|
||||||
|
|
||||||
if (edev->max_supported == 0)
|
if (edev->max_supported == 0)
|
||||||
return sprintf(buf, "%u\n", edev->state);
|
return sprintf(buf, "%u\n", edev->state);
|
||||||
|
|
||||||
|
@ -272,6 +264,9 @@ int extcon_update_state(struct extcon_dev *edev, u32 mask, u32 state)
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
bool attached;
|
bool attached;
|
||||||
|
|
||||||
|
if (!edev)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
spin_lock_irqsave(&edev->lock, flags);
|
spin_lock_irqsave(&edev->lock, flags);
|
||||||
|
|
||||||
if (edev->state != ((edev->state & ~mask) | (state & mask))) {
|
if (edev->state != ((edev->state & ~mask) | (state & mask))) {
|
||||||
|
@ -345,6 +340,9 @@ EXPORT_SYMBOL_GPL(extcon_update_state);
|
||||||
*/
|
*/
|
||||||
int extcon_set_state(struct extcon_dev *edev, u32 state)
|
int extcon_set_state(struct extcon_dev *edev, u32 state)
|
||||||
{
|
{
|
||||||
|
if (!edev)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
return extcon_update_state(edev, 0xffffffff, state);
|
return extcon_update_state(edev, 0xffffffff, state);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(extcon_set_state);
|
EXPORT_SYMBOL_GPL(extcon_set_state);
|
||||||
|
@ -358,6 +356,9 @@ int extcon_get_cable_state_(struct extcon_dev *edev, const unsigned int id)
|
||||||
{
|
{
|
||||||
int index;
|
int index;
|
||||||
|
|
||||||
|
if (!edev)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
index = find_cable_index_by_id(edev, id);
|
index = find_cable_index_by_id(edev, id);
|
||||||
if (index < 0)
|
if (index < 0)
|
||||||
return index;
|
return index;
|
||||||
|
@ -378,7 +379,7 @@ EXPORT_SYMBOL_GPL(extcon_get_cable_state_);
|
||||||
*/
|
*/
|
||||||
int extcon_get_cable_state(struct extcon_dev *edev, const char *cable_name)
|
int extcon_get_cable_state(struct extcon_dev *edev, const char *cable_name)
|
||||||
{
|
{
|
||||||
unsigned int id;
|
int id;
|
||||||
|
|
||||||
id = find_cable_id_by_name(edev, cable_name);
|
id = find_cable_id_by_name(edev, cable_name);
|
||||||
if (id < 0)
|
if (id < 0)
|
||||||
|
@ -402,6 +403,9 @@ int extcon_set_cable_state_(struct extcon_dev *edev, unsigned int id,
|
||||||
u32 state;
|
u32 state;
|
||||||
int index;
|
int index;
|
||||||
|
|
||||||
|
if (!edev)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
index = find_cable_index_by_id(edev, id);
|
index = find_cable_index_by_id(edev, id);
|
||||||
if (index < 0)
|
if (index < 0)
|
||||||
return index;
|
return index;
|
||||||
|
@ -426,7 +430,7 @@ EXPORT_SYMBOL_GPL(extcon_set_cable_state_);
|
||||||
int extcon_set_cable_state(struct extcon_dev *edev,
|
int extcon_set_cable_state(struct extcon_dev *edev,
|
||||||
const char *cable_name, bool cable_state)
|
const char *cable_name, bool cable_state)
|
||||||
{
|
{
|
||||||
unsigned int id;
|
int id;
|
||||||
|
|
||||||
id = find_cable_id_by_name(edev, cable_name);
|
id = find_cable_id_by_name(edev, cable_name);
|
||||||
if (id < 0)
|
if (id < 0)
|
||||||
|
@ -444,6 +448,9 @@ struct extcon_dev *extcon_get_extcon_dev(const char *extcon_name)
|
||||||
{
|
{
|
||||||
struct extcon_dev *sd;
|
struct extcon_dev *sd;
|
||||||
|
|
||||||
|
if (!extcon_name)
|
||||||
|
return ERR_PTR(-EINVAL);
|
||||||
|
|
||||||
mutex_lock(&extcon_dev_list_lock);
|
mutex_lock(&extcon_dev_list_lock);
|
||||||
list_for_each_entry(sd, &extcon_dev_list, entry) {
|
list_for_each_entry(sd, &extcon_dev_list, entry) {
|
||||||
if (!strcmp(sd->name, extcon_name))
|
if (!strcmp(sd->name, extcon_name))
|
||||||
|
@ -572,6 +579,9 @@ int extcon_register_notifier(struct extcon_dev *edev, unsigned int id,
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
int ret, idx;
|
int ret, idx;
|
||||||
|
|
||||||
|
if (!edev || !nb)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
idx = find_cable_index_by_id(edev, id);
|
idx = find_cable_index_by_id(edev, id);
|
||||||
|
|
||||||
spin_lock_irqsave(&edev->lock, flags);
|
spin_lock_irqsave(&edev->lock, flags);
|
||||||
|
@ -594,6 +604,9 @@ int extcon_unregister_notifier(struct extcon_dev *edev, unsigned int id,
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
int ret, idx;
|
int ret, idx;
|
||||||
|
|
||||||
|
if (!edev || !nb)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
idx = find_cable_index_by_id(edev, id);
|
idx = find_cable_index_by_id(edev, id);
|
||||||
|
|
||||||
spin_lock_irqsave(&edev->lock, flags);
|
spin_lock_irqsave(&edev->lock, flags);
|
||||||
|
@ -654,6 +667,9 @@ struct extcon_dev *extcon_dev_allocate(const unsigned int *supported_cable)
|
||||||
{
|
{
|
||||||
struct extcon_dev *edev;
|
struct extcon_dev *edev;
|
||||||
|
|
||||||
|
if (!supported_cable)
|
||||||
|
return ERR_PTR(-EINVAL);
|
||||||
|
|
||||||
edev = kzalloc(sizeof(*edev), GFP_KERNEL);
|
edev = kzalloc(sizeof(*edev), GFP_KERNEL);
|
||||||
if (!edev)
|
if (!edev)
|
||||||
return ERR_PTR(-ENOMEM);
|
return ERR_PTR(-ENOMEM);
|
||||||
|
@ -754,7 +770,7 @@ int extcon_dev_register(struct extcon_dev *edev)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!edev->supported_cable)
|
if (!edev || !edev->supported_cable)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
for (; edev->supported_cable[index] != EXTCON_NONE; index++);
|
for (; edev->supported_cable[index] != EXTCON_NONE; index++);
|
||||||
|
@ -960,6 +976,9 @@ void extcon_dev_unregister(struct extcon_dev *edev)
|
||||||
{
|
{
|
||||||
int index;
|
int index;
|
||||||
|
|
||||||
|
if (!edev)
|
||||||
|
return;
|
||||||
|
|
||||||
mutex_lock(&extcon_dev_list_lock);
|
mutex_lock(&extcon_dev_list_lock);
|
||||||
list_del(&edev->entry);
|
list_del(&edev->entry);
|
||||||
mutex_unlock(&extcon_dev_list_lock);
|
mutex_unlock(&extcon_dev_list_lock);
|
||||||
|
@ -1066,6 +1085,9 @@ struct extcon_dev *extcon_get_edev_by_phandle(struct device *dev, int index)
|
||||||
struct device_node *node;
|
struct device_node *node;
|
||||||
struct extcon_dev *edev;
|
struct extcon_dev *edev;
|
||||||
|
|
||||||
|
if (!dev)
|
||||||
|
return ERR_PTR(-EINVAL);
|
||||||
|
|
||||||
if (!dev->of_node) {
|
if (!dev->of_node) {
|
||||||
dev_err(dev, "device does not have a device node entry\n");
|
dev_err(dev, "device does not have a device node entry\n");
|
||||||
return ERR_PTR(-EINVAL);
|
return ERR_PTR(-EINVAL);
|
||||||
|
|
|
@ -27,8 +27,6 @@
|
||||||
#define __LINUX_EXTCON_H__
|
#define __LINUX_EXTCON_H__
|
||||||
|
|
||||||
#include <linux/device.h>
|
#include <linux/device.h>
|
||||||
#include <linux/notifier.h>
|
|
||||||
#include <linux/sysfs.h>
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Define the unique id of supported external connectors
|
* Define the unique id of supported external connectors
|
||||||
|
@ -77,8 +75,6 @@ struct extcon_cable;
|
||||||
* be attached simulataneously. {0x7, 0} is equivalent to
|
* be attached simulataneously. {0x7, 0} is equivalent to
|
||||||
* {0x3, 0x6, 0x5, 0}. If it is {0xFFFFFFFF, 0}, there
|
* {0x3, 0x6, 0x5, 0}. If it is {0xFFFFFFFF, 0}, there
|
||||||
* can be no simultaneous connections.
|
* can be no simultaneous connections.
|
||||||
* @print_state: An optional callback to override the method to print the
|
|
||||||
* status of the extcon device.
|
|
||||||
* @dev: Device of this extcon.
|
* @dev: Device of this extcon.
|
||||||
* @state: Attach/detach state of this extcon. Do not provide at
|
* @state: Attach/detach state of this extcon. Do not provide at
|
||||||
* register-time.
|
* register-time.
|
||||||
|
@ -102,9 +98,6 @@ struct extcon_dev {
|
||||||
const unsigned int *supported_cable;
|
const unsigned int *supported_cable;
|
||||||
const u32 *mutually_exclusive;
|
const u32 *mutually_exclusive;
|
||||||
|
|
||||||
/* Optional callbacks to override class functions */
|
|
||||||
ssize_t (*print_state)(struct extcon_dev *edev, char *buf);
|
|
||||||
|
|
||||||
/* Internal data. Please do not set. */
|
/* Internal data. Please do not set. */
|
||||||
struct device dev;
|
struct device dev;
|
||||||
struct raw_notifier_head *nh;
|
struct raw_notifier_head *nh;
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#include <linux/regmap.h>
|
#include <linux/regmap.h>
|
||||||
#include <linux/regulator/driver.h>
|
#include <linux/regulator/driver.h>
|
||||||
#include <linux/extcon.h>
|
#include <linux/extcon.h>
|
||||||
|
#include <linux/of_gpio.h>
|
||||||
#include <linux/usb/phy_companion.h>
|
#include <linux/usb/phy_companion.h>
|
||||||
|
|
||||||
#define PALMAS_NUM_CLIENTS 3
|
#define PALMAS_NUM_CLIENTS 3
|
||||||
|
@ -551,10 +552,16 @@ struct palmas_usb {
|
||||||
int vbus_otg_irq;
|
int vbus_otg_irq;
|
||||||
int vbus_irq;
|
int vbus_irq;
|
||||||
|
|
||||||
|
int gpio_id_irq;
|
||||||
|
struct gpio_desc *id_gpiod;
|
||||||
|
unsigned long sw_debounce_jiffies;
|
||||||
|
struct delayed_work wq_detectid;
|
||||||
|
|
||||||
enum palmas_usb_state linkstat;
|
enum palmas_usb_state linkstat;
|
||||||
int wakeup;
|
int wakeup;
|
||||||
bool enable_vbus_detection;
|
bool enable_vbus_detection;
|
||||||
bool enable_id_detection;
|
bool enable_id_detection;
|
||||||
|
bool enable_gpio_id_detection;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define comparator_to_palmas(x) container_of((x), struct palmas_usb, comparator)
|
#define comparator_to_palmas(x) container_of((x), struct palmas_usb, comparator)
|
||||||
|
|
Loading…
Reference in New Issue