Commit 672cfeeb authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

Merge tag 'extcon-next-for-4.3' of...

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
parents 92f26189 ac22a1d3
......@@ -10,8 +10,11 @@ Required Properties:
Optional Properties:
- 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.
- id-gpio: gpio for GPIO ID detection. See gpio binding.
- debounce-delay-ms: debounce delay for GPIO ID pin in milliseconds.
palmas-usb {
compatible = "ti,twl6035-usb", "ti,palmas-usb";
......
......@@ -20,10 +20,12 @@
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/err.h>
#include <linux/gpio/consumer.h>
#include <linux/gpio.h>
#include <linux/input.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/property.h>
#include <linux/regulator/consumer.h>
#include <linux/extcon.h>
......@@ -46,6 +48,9 @@
#define HPDET_DEBOUNCE 500
#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 | \
ARIZONA_MICD_LVL_3 | ARIZONA_MICD_LVL_4 | \
ARIZONA_MICD_LVL_5 | ARIZONA_MICD_LVL_6 | \
......@@ -94,6 +99,8 @@ struct arizona_extcon_info {
int hpdet_ip_version;
struct extcon_dev *edev;
struct gpio_desc *micd_pol_gpio;
};
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)
gpio_set_value_cansleep(arizona->pdata.micd_pol_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,
ARIZONA_MICD_BIAS_SRC_MASK,
info->micd_modes[mode].bias <<
......@@ -757,10 +768,11 @@ static void arizona_micd_timeout_work(struct work_struct *work)
mutex_lock(&info->lock);
dev_dbg(info->arizona->dev, "MICD timed out, reporting HP\n");
arizona_identify_headphone(info);
info->detecting = false;
arizona_identify_headphone(info);
arizona_stop_mic(info);
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 */
if (!(val & ARIZONA_MICD_STS)) {
dev_warn(arizona->dev, "Detected open circuit\n");
info->mic = false;
arizona_stop_mic(info);
info->detecting = false;
arizona_identify_headphone(info);
goto handled;
}
/* If we got a high impedence we should have a headset, report it. */
if (info->detecting && (val & ARIZONA_MICD_LVL_8)) {
info->mic = true;
info->detecting = false;
arizona_identify_headphone(info);
ret = extcon_set_cable_state_(info->edev,
......@@ -841,8 +859,6 @@ static void arizona_micd_detect(struct work_struct *work)
ret);
}
info->mic = true;
info->detecting = false;
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->jack_flips >= info->micd_num_modes * 10) {
dev_dbg(arizona->dev, "Detected HP/line\n");
arizona_identify_headphone(info);
info->detecting = false;
arizona_identify_headphone(info);
arizona_stop_mic(info);
} else {
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);
}
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;
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) {
case ARIZONA_ACCDET_MODE_HPL:
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;
}
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;
}
......@@ -1147,10 +1182,8 @@ static int arizona_extcon_probe(struct platform_device *pdev)
if (!info)
return -ENOMEM;
if (IS_ENABLED(CONFIG_OF)) {
if (!dev_get_platdata(arizona->dev))
arizona_extcon_of_get_pdata(arizona);
}
if (!dev_get_platdata(arizona->dev))
arizona_extcon_device_get_pdata(arizona);
info->micvdd = devm_regulator_get(&pdev->dev, "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);
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) {
......@@ -1251,7 +1305,7 @@ static int arizona_extcon_probe(struct platform_device *pdev)
if (ret != 0) {
dev_err(arizona->dev, "Failed to request GPIO%d: %d\n",
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_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,
ARIZONA_MICD_DBTIME_MASK,
arizona->pdata.micd_dbtime
<< ARIZONA_MICD_DBTIME_SHIFT);
ARIZONA_MICD_DBTIME);
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);
......@@ -1295,7 +1357,7 @@ static int arizona_extcon_probe(struct platform_device *pdev)
dev_err(arizona->dev,
"MICD ranges must be sorted\n");
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",
info->micd_ranges[i].max);
ret = -EINVAL;
goto err_input;
goto err_gpio;
}
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) {
dev_err(&pdev->dev, "Failed to get JACKDET rise IRQ: %d\n",
ret);
goto err_input;
goto err_gpio;
}
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);
err_rise:
arizona_free_irq(arizona, jack_irq_rise, info);
err_input:
err_gpio:
gpiod_put(info->micd_pol_gpio);
err_register:
pm_runtime_disable(&pdev->dev);
return ret;
......@@ -1470,6 +1533,8 @@ static int arizona_extcon_remove(struct platform_device *pdev)
struct arizona *arizona = info->arizona;
int jack_irq_rise, jack_irq_fall;
gpiod_put(info->micd_pol_gpio);
pm_runtime_disable(&pdev->dev);
regmap_update_bits(arizona->regmap,
......
......@@ -65,22 +65,6 @@ static irqreturn_t gpio_irq_handler(int irq, void *dev_id)
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)
{
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_off = pdata->state_off;
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,
pdev->name);
......
......@@ -781,6 +781,15 @@ static int max77843_muic_probe(struct platform_device *pdev)
/* Support virtual irq domain for max77843 MUIC device */
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++) {
struct max77843_muic_irq *muic_irq = &max77843_muic_irqs[i];
unsigned int virq = 0;
......
......@@ -28,6 +28,11 @@
#include <linux/mfd/palmas.h>
#include <linux/of.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[] = {
EXTCON_USB,
......@@ -35,8 +40,6 @@ static const unsigned int palmas_extcon_cable[] = {
EXTCON_NONE,
};
static const int mutually_exclusive[] = {0x3, 0x0};
static void palmas_usb_wakeup(struct palmas *palmas, int enable)
{
if (enable)
......@@ -120,19 +123,54 @@ static irqreturn_t palmas_id_irq_handler(int irq, void *_palmas_usb)
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)
{
palmas_write(palmas_usb->palmas, PALMAS_USB_OTG_BASE,
PALMAS_USB_VBUS_CTRL_SET,
PALMAS_USB_VBUS_CTRL_SET_VBUS_ACT_COMP);
palmas_write(palmas_usb->palmas, PALMAS_USB_OTG_BASE,
PALMAS_USB_ID_CTRL_SET, PALMAS_USB_ID_CTRL_SET_ID_ACT_COMP);
if (palmas_usb->enable_id_detection) {
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_USB_ID_INT_EN_HI_SET,
PALMAS_USB_ID_INT_EN_HI_SET_ID_GND |
PALMAS_USB_ID_INT_EN_HI_SET_ID_FLOAT);
palmas_write(palmas_usb->palmas, PALMAS_USB_OTG_BASE,
PALMAS_USB_ID_INT_EN_HI_SET,
PALMAS_USB_ID_INT_EN_HI_SET_ID_GND |
PALMAS_USB_ID_INT_EN_HI_SET_ID_FLOAT);
}
if (palmas_usb->enable_vbus_detection)
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->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 = palmas;
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);
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");
return -ENOMEM;
}
palmas_usb->edev->mutually_exclusive = mutually_exclusive;
status = devm_extcon_dev_register(&pdev->dev, palmas_usb->edev);
if (status) {
......@@ -204,6 +258,10 @@ static int palmas_usb_probe(struct platform_device *pdev)
}
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,
palmas_usb->id_irq,
NULL, palmas_id_irq_handler,
......@@ -215,9 +273,33 @@ static int palmas_usb_probe(struct platform_device *pdev)
palmas_usb->id_irq, 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) {
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,
palmas_usb->vbus_irq, NULL,
palmas_vbus_irq_handler,
......@@ -232,10 +314,21 @@ static int palmas_usb_probe(struct platform_device *pdev)
}
palmas_enable_irq(palmas_usb);
/* perform initial detection */
palmas_gpio_id_detect(&palmas_usb->wq_detectid.work);
device_set_wakeup_capable(&pdev->dev, true);
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
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);
if (palmas_usb->enable_id_detection)
enable_irq_wake(palmas_usb->id_irq);
if (palmas_usb->enable_gpio_id_detection)
enable_irq_wake(palmas_usb->gpio_id_irq);
}
return 0;
}
......@@ -259,6 +354,8 @@ static int palmas_usb_resume(struct device *dev)
disable_irq_wake(palmas_usb->vbus_irq);
if (palmas_usb->enable_id_detection)
disable_irq_wake(palmas_usb->id_irq);
if (palmas_usb->enable_gpio_id_detection)
disable_irq_wake(palmas_usb->gpio_id_irq);
}
return 0;
};
......@@ -276,6 +373,7 @@ static const struct of_device_id of_palmas_match_tbl[] = {
static struct platform_driver palmas_usb_driver = {
.probe = palmas_usb_probe,
.remove = palmas_usb_remove,
.driver = {
.name = "palmas-usb",
.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 = {
.driver = {
.name = "rt8973a",
.owner = THIS_MODULE,
.pm = &rt8973a_muic_pm_ops,
.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 = {
.driver = {
.name = "sm5502",
.owner = THIS_MODULE,
.pm = &sm5502_muic_pm_ops,
.of_match_table = sm5502_dt_match,
},
......
......@@ -15,6 +15,7 @@
*/
#include <linux/extcon.h>
#include <linux/gpio.h>
#include <linux/gpio/consumer.h>
#include <linux/init.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)
{
unsigned int id = -EINVAL;
int id = -EINVAL;
int i = 0;
/* 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)
{
unsigned int id;
int id;
if (edev->max_supported == 0)
return -EINVAL;
......@@ -172,14 +172,6 @@ static ssize_t state_show(struct device *dev, struct device_attribute *attr,
int i, count = 0;
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)
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;
bool attached;
if (!edev)
return -EINVAL;
spin_lock_irqsave(&edev->lock, flags);
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)
{
if (!edev)
return -EINVAL;
return extcon_update_state(edev, 0xffffffff, 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;
if (!edev)
return -EINVAL;
index = find_cable_index_by_id(edev, id);
if (index < 0)
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)
{
unsigned int id;
int id;
id = find_cable_id_by_name(edev, cable_name);
if (id < 0)
......@@ -402,6 +403,9 @@ int extcon_set_cable_state_(struct extcon_dev *edev, unsigned int id,
u32 state;
int index;
if (!edev)
return -EINVAL;
index = find_cable_index_by_id(edev, id);
if (index < 0)
return index;
......@@ -426,7 +430,7 @@ EXPORT_SYMBOL_GPL(extcon_set_cable_state_);
int extcon_set_cable_state(struct extcon_dev *edev,
const char *cable_name, bool cable_state)
{
unsigned int id;
int id;
id = find_cable_id_by_name(edev, cable_name);
if (id < 0)
......@@ -444,6 +448,9 @@ struct extcon_dev *extcon_get_extcon_dev(const char *extcon_name)
{
struct extcon_dev *sd;
if (!extcon_name)
return ERR_PTR(-EINVAL);
mutex_lock(&extcon_dev_list_lock);
list_for_each_entry(sd, &extcon_dev_list, entry) {
if (!strcmp(sd->name, extcon_name))
......@@ -572,6 +579,9 @@ int extcon_register_notifier(struct extcon_dev *edev, unsigned int id,
unsigned long flags;
int ret, idx;
if (!edev || !nb)
return -EINVAL;
idx = find_cable_index_by_id(edev, id);
spin_lock_irqsave(&edev->lock, flags);
......@@ -594,6 +604,9 @@ int extcon_unregister_notifier(struct extcon_dev *edev, unsigned int id,
unsigned long flags;
int ret, idx;
if (!edev || !nb)
return -EINVAL;
idx = find_cable_index_by_id(edev, id);
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;
if (!supported_cable)
return ERR_PTR(-EINVAL);
edev = kzalloc(sizeof(*edev), GFP_KERNEL);
if (!edev)
return ERR_PTR(-ENOMEM);
......@@ -754,7 +770,7 @@ int extcon_dev_register(struct extcon_dev *edev)
return ret;
}
if (!edev->supported_cable)
if (!edev || !edev->supported_cable)
return -EINVAL;
for (; edev->supported_cable[index] != EXTCON_NONE; index++);
......@@ -960,6 +976,9 @@ void extcon_dev_unregister(struct extcon_dev *edev)
{
int index;
if (!edev)
return;
mutex_lock(&extcon_dev_list_lock);
list_del(&edev->entry);
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 extcon_dev *edev;
if (!dev)
return ERR_PTR(-EINVAL);
if (!dev->of_node) {
dev_err(dev, "device does not have a device node entry\n");
return ERR_PTR(-EINVAL);
......
......@@ -27,8 +27,6 @@
#define __LINUX_EXTCON_H__
#include <linux/device.h>
#include <linux/notifier.h>
#include <linux/sysfs.h>
/*
* Define the unique id of supported external connectors
......@@ -77,8 +75,6 @@ struct extcon_cable;
* be attached simulataneously. {0x7, 0} is equivalent to
* {0x3, 0x6, 0x5, 0}. If it is {0xFFFFFFFF, 0}, there
* 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.
* @state: Attach/detach state of this extcon. Do not provide at
* register-time.
......@@ -102,9 +98,6 @@ struct extcon_dev {
const unsigned int *supported_cable;
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. */
struct device dev;
struct raw_notifier_head *nh;
......
......@@ -21,6 +21,7 @@
#include <linux/regmap.h>
#include <linux/regulator/driver.h>
#include <linux/extcon.h>
#include <linux/of_gpio.h>
#include <linux/usb/phy_companion.h>
#define PALMAS_NUM_CLIENTS 3
......@@ -551,10 +552,16 @@ struct palmas_usb {
int vbus_otg_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;
int wakeup;
bool enable_vbus_detection;
bool enable_id_detection;
bool enable_gpio_id_detection;
};
#define comparator_to_palmas(x) container_of((x), struct palmas_usb, comparator)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment