Commit e727efee authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

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

Merge tag 'extcon-next-for-5.19' of git://git.kernel.org/pub/scm/linux/kernel/git/chanwoo/extcon into char-misc-next

Chanwoo writes:

Update extcon next for v5.19

Detailed description for this pull request:
1. update extcon core driver
- extcon_get_extcon_dev() has been almost used to get the extcon device
on booting time. If extcon provider driver is probed at late time,
the extcon consumer driver get the -EPROBE_DEFER return value.
It requires the inefficient handling code of -EPROBE_DEFER.
Instead, extcon_get_extcon_dev() will return -EPROBE_DEFER
if the required extcon device is none. It makes the extcon consumer driver
to be simplified when getting extcon device.
- Register device after dev_set_drvdata because of accessing
the sysfs attributes at timing of between drv_set_data and device_register.
- Fix some kernel-doc comments of extcon functions.

2. update extcon provider driver
- Update extcon-intel-int3496.c
: Add support for controlling vbus power via regulator and support
to the extcon-intel-int3496.c driver to bind to devices without
an ACPi companion. And fix the minor clean-up.
- Use struct_size() helper on extcon-usbc-cros-ec.c
- Remove the disable irq operation in system sleep for using vbus/id
gpio as the wakeup source on extcon-usb-gpio.c
- Add support of SM5703 device by using existing extcon-sm5502.c
and rename i2c_devic_id from sm5703 to sm5703-muic to reduce confusion
between SM5703 MFD device and extcon device.
- Add usb role class support and add queue work sync before driver release
on extcon-ptn5150.c

* tag 'extcon-next-for-5.19' of git://git.kernel.org/pub/scm/linux/kernel/git/chanwoo/extcon:
  extcon: Modify extcon device to be created after driver data is set
  extcon: sm5502: Clarify SM5703's i2c device ID
  extcon: ptn5150: Add usb role class support
  extcon: ptn5150: Add queue work sync before driver release
  extcon: sm5502: Add support for SM5703
  dt-bindings: extcon: bindings for SM5703
  extcon: usb-gpio: Remove disable irq operation in system sleep
  extcon: Fix some kernel-doc comments
  extcon: usbc-cros-ec: Use struct_size() helper in kzalloc()
  extcon: int3496: Add support for controlling Vbus through a regulator
  extcon: int3496: Add support for binding to plain platform devices
  extcon: int3496: Request non-exclusive access to the ID GPIO
  extcon: int3496: Make the driver a bit less verbose
  extcon: Fix extcon_get_extcon_dev() error handling
parents fa5602c6 5dcc2afe
...@@ -20,11 +20,12 @@ properties: ...@@ -20,11 +20,12 @@ properties:
enum: enum:
- siliconmitus,sm5502-muic - siliconmitus,sm5502-muic
- siliconmitus,sm5504-muic - siliconmitus,sm5504-muic
- siliconmitus,sm5703-muic
reg: reg:
maxItems: 1 maxItems: 1
description: I2C slave address of the device. Usually 0x25 for SM5502, description: I2C slave address of the device. Usually 0x25 for SM5502
0x14 for SM5504. and SM5703, 0x14 for SM5504.
interrupts: interrupts:
maxItems: 1 maxItems: 1
......
...@@ -131,6 +131,7 @@ config EXTCON_PALMAS ...@@ -131,6 +131,7 @@ config EXTCON_PALMAS
config EXTCON_PTN5150 config EXTCON_PTN5150
tristate "NXP PTN5150 CC LOGIC USB EXTCON support" tristate "NXP PTN5150 CC LOGIC USB EXTCON support"
depends on I2C && (GPIOLIB || COMPILE_TEST) depends on I2C && (GPIOLIB || COMPILE_TEST)
depends on USB_ROLE_SWITCH || !USB_ROLE_SWITCH
select REGMAP_I2C select REGMAP_I2C
help help
Say Y here to enable support for USB peripheral and USB host Say Y here to enable support for USB peripheral and USB host
...@@ -156,7 +157,7 @@ config EXTCON_RT8973A ...@@ -156,7 +157,7 @@ config EXTCON_RT8973A
from abnormal high input voltage (up to 28V). from abnormal high input voltage (up to 28V).
config EXTCON_SM5502 config EXTCON_SM5502
tristate "Silicon Mitus SM5502/SM5504 EXTCON support" tristate "Silicon Mitus SM5502/SM5504/SM5703 EXTCON support"
depends on I2C depends on I2C
select IRQ_DOMAIN select IRQ_DOMAIN
select REGMAP_I2C select REGMAP_I2C
......
...@@ -394,8 +394,8 @@ static int axp288_extcon_probe(struct platform_device *pdev) ...@@ -394,8 +394,8 @@ static int axp288_extcon_probe(struct platform_device *pdev)
if (adev) { if (adev) {
info->id_extcon = extcon_get_extcon_dev(acpi_dev_name(adev)); info->id_extcon = extcon_get_extcon_dev(acpi_dev_name(adev));
put_device(&adev->dev); put_device(&adev->dev);
if (!info->id_extcon) if (IS_ERR(info->id_extcon))
return -EPROBE_DEFER; return PTR_ERR(info->id_extcon);
dev_info(dev, "controlling USB role\n"); dev_info(dev, "controlling USB role\n");
} else { } else {
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/regulator/consumer.h>
#define INT3496_GPIO_USB_ID 0 #define INT3496_GPIO_USB_ID 0
#define INT3496_GPIO_VBUS_EN 1 #define INT3496_GPIO_VBUS_EN 1
...@@ -30,7 +31,9 @@ struct int3496_data { ...@@ -30,7 +31,9 @@ struct int3496_data {
struct gpio_desc *gpio_usb_id; struct gpio_desc *gpio_usb_id;
struct gpio_desc *gpio_vbus_en; struct gpio_desc *gpio_vbus_en;
struct gpio_desc *gpio_usb_mux; struct gpio_desc *gpio_usb_mux;
struct regulator *vbus_boost;
int usb_id_irq; int usb_id_irq;
bool vbus_boost_enabled;
}; };
static const unsigned int int3496_cable[] = { static const unsigned int int3496_cable[] = {
...@@ -53,6 +56,27 @@ static const struct acpi_gpio_mapping acpi_int3496_default_gpios[] = { ...@@ -53,6 +56,27 @@ static const struct acpi_gpio_mapping acpi_int3496_default_gpios[] = {
{ }, { },
}; };
static void int3496_set_vbus_boost(struct int3496_data *data, bool enable)
{
int ret;
if (IS_ERR_OR_NULL(data->vbus_boost))
return;
if (data->vbus_boost_enabled == enable)
return;
if (enable)
ret = regulator_enable(data->vbus_boost);
else
ret = regulator_disable(data->vbus_boost);
if (ret == 0)
data->vbus_boost_enabled = enable;
else
dev_err(data->dev, "Error updating Vbus boost regulator: %d\n", ret);
}
static void int3496_do_usb_id(struct work_struct *work) static void int3496_do_usb_id(struct work_struct *work)
{ {
struct int3496_data *data = struct int3496_data *data =
...@@ -71,6 +95,8 @@ static void int3496_do_usb_id(struct work_struct *work) ...@@ -71,6 +95,8 @@ static void int3496_do_usb_id(struct work_struct *work)
if (!IS_ERR(data->gpio_vbus_en)) if (!IS_ERR(data->gpio_vbus_en))
gpiod_direction_output(data->gpio_vbus_en, !id); gpiod_direction_output(data->gpio_vbus_en, !id);
else
int3496_set_vbus_boost(data, !id);
extcon_set_state_sync(data->edev, EXTCON_USB_HOST, !id); extcon_set_state_sync(data->edev, EXTCON_USB_HOST, !id);
} }
...@@ -91,10 +117,12 @@ static int int3496_probe(struct platform_device *pdev) ...@@ -91,10 +117,12 @@ static int int3496_probe(struct platform_device *pdev)
struct int3496_data *data; struct int3496_data *data;
int ret; int ret;
ret = devm_acpi_dev_add_driver_gpios(dev, acpi_int3496_default_gpios); if (has_acpi_companion(dev)) {
if (ret) { ret = devm_acpi_dev_add_driver_gpios(dev, acpi_int3496_default_gpios);
dev_err(dev, "can't add GPIO ACPI mapping\n"); if (ret) {
return ret; dev_err(dev, "can't add GPIO ACPI mapping\n");
return ret;
}
} }
data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
...@@ -106,7 +134,8 @@ static int int3496_probe(struct platform_device *pdev) ...@@ -106,7 +134,8 @@ static int int3496_probe(struct platform_device *pdev)
if (ret) if (ret)
return ret; return ret;
data->gpio_usb_id = devm_gpiod_get(dev, "id", GPIOD_IN); data->gpio_usb_id =
devm_gpiod_get(dev, "id", GPIOD_IN | GPIOD_FLAGS_BIT_NONEXCLUSIVE);
if (IS_ERR(data->gpio_usb_id)) { if (IS_ERR(data->gpio_usb_id)) {
ret = PTR_ERR(data->gpio_usb_id); ret = PTR_ERR(data->gpio_usb_id);
dev_err(dev, "can't request USB ID GPIO: %d\n", ret); dev_err(dev, "can't request USB ID GPIO: %d\n", ret);
...@@ -120,12 +149,14 @@ static int int3496_probe(struct platform_device *pdev) ...@@ -120,12 +149,14 @@ static int int3496_probe(struct platform_device *pdev)
} }
data->gpio_vbus_en = devm_gpiod_get(dev, "vbus", GPIOD_ASIS); data->gpio_vbus_en = devm_gpiod_get(dev, "vbus", GPIOD_ASIS);
if (IS_ERR(data->gpio_vbus_en)) if (IS_ERR(data->gpio_vbus_en)) {
dev_info(dev, "can't request VBUS EN GPIO\n"); dev_dbg(dev, "can't request VBUS EN GPIO\n");
data->vbus_boost = devm_regulator_get_optional(dev, "vbus");
}
data->gpio_usb_mux = devm_gpiod_get(dev, "mux", GPIOD_ASIS); data->gpio_usb_mux = devm_gpiod_get(dev, "mux", GPIOD_ASIS);
if (IS_ERR(data->gpio_usb_mux)) if (IS_ERR(data->gpio_usb_mux))
dev_info(dev, "can't request USB MUX GPIO\n"); dev_dbg(dev, "can't request USB MUX GPIO\n");
/* register extcon device */ /* register extcon device */
data->edev = devm_extcon_dev_allocate(dev, int3496_cable); data->edev = devm_extcon_dev_allocate(dev, int3496_cable);
...@@ -164,12 +195,19 @@ static const struct acpi_device_id int3496_acpi_match[] = { ...@@ -164,12 +195,19 @@ static const struct acpi_device_id int3496_acpi_match[] = {
}; };
MODULE_DEVICE_TABLE(acpi, int3496_acpi_match); MODULE_DEVICE_TABLE(acpi, int3496_acpi_match);
static const struct platform_device_id int3496_ids[] = {
{ .name = "intel-int3496" },
{},
};
MODULE_DEVICE_TABLE(platform, int3496_ids);
static struct platform_driver int3496_driver = { static struct platform_driver int3496_driver = {
.driver = { .driver = {
.name = "intel-int3496", .name = "intel-int3496",
.acpi_match_table = int3496_acpi_match, .acpi_match_table = int3496_acpi_match,
}, },
.probe = int3496_probe, .probe = int3496_probe,
.id_table = int3496_ids,
}; };
module_platform_driver(int3496_driver); module_platform_driver(int3496_driver);
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/extcon-provider.h> #include <linux/extcon-provider.h>
#include <linux/gpio/consumer.h> #include <linux/gpio/consumer.h>
#include <linux/usb/role.h>
/* PTN5150 registers */ /* PTN5150 registers */
#define PTN5150_REG_DEVICE_ID 0x01 #define PTN5150_REG_DEVICE_ID 0x01
...@@ -52,6 +53,7 @@ struct ptn5150_info { ...@@ -52,6 +53,7 @@ struct ptn5150_info {
int irq; int irq;
struct work_struct irq_work; struct work_struct irq_work;
struct mutex mutex; struct mutex mutex;
struct usb_role_switch *role_sw;
}; };
/* List of detectable cables */ /* List of detectable cables */
...@@ -70,6 +72,7 @@ static const struct regmap_config ptn5150_regmap_config = { ...@@ -70,6 +72,7 @@ static const struct regmap_config ptn5150_regmap_config = {
static void ptn5150_check_state(struct ptn5150_info *info) static void ptn5150_check_state(struct ptn5150_info *info)
{ {
unsigned int port_status, reg_data, vbus; unsigned int port_status, reg_data, vbus;
enum usb_role usb_role = USB_ROLE_NONE;
int ret; int ret;
ret = regmap_read(info->regmap, PTN5150_REG_CC_STATUS, &reg_data); ret = regmap_read(info->regmap, PTN5150_REG_CC_STATUS, &reg_data);
...@@ -85,6 +88,7 @@ static void ptn5150_check_state(struct ptn5150_info *info) ...@@ -85,6 +88,7 @@ static void ptn5150_check_state(struct ptn5150_info *info)
extcon_set_state_sync(info->edev, EXTCON_USB_HOST, false); extcon_set_state_sync(info->edev, EXTCON_USB_HOST, false);
gpiod_set_value_cansleep(info->vbus_gpiod, 0); gpiod_set_value_cansleep(info->vbus_gpiod, 0);
extcon_set_state_sync(info->edev, EXTCON_USB, true); extcon_set_state_sync(info->edev, EXTCON_USB, true);
usb_role = USB_ROLE_DEVICE;
break; break;
case PTN5150_UFP_ATTACHED: case PTN5150_UFP_ATTACHED:
extcon_set_state_sync(info->edev, EXTCON_USB, false); extcon_set_state_sync(info->edev, EXTCON_USB, false);
...@@ -95,10 +99,18 @@ static void ptn5150_check_state(struct ptn5150_info *info) ...@@ -95,10 +99,18 @@ static void ptn5150_check_state(struct ptn5150_info *info)
gpiod_set_value_cansleep(info->vbus_gpiod, 1); gpiod_set_value_cansleep(info->vbus_gpiod, 1);
extcon_set_state_sync(info->edev, EXTCON_USB_HOST, true); extcon_set_state_sync(info->edev, EXTCON_USB_HOST, true);
usb_role = USB_ROLE_HOST;
break; break;
default: default:
break; break;
} }
if (usb_role) {
ret = usb_role_switch_set_role(info->role_sw, usb_role);
if (ret)
dev_err(info->dev, "failed to set %s role: %d\n",
usb_role_string(usb_role), ret);
}
} }
static void ptn5150_irq_work(struct work_struct *work) static void ptn5150_irq_work(struct work_struct *work)
...@@ -133,6 +145,13 @@ static void ptn5150_irq_work(struct work_struct *work) ...@@ -133,6 +145,13 @@ static void ptn5150_irq_work(struct work_struct *work)
extcon_set_state_sync(info->edev, extcon_set_state_sync(info->edev,
EXTCON_USB, false); EXTCON_USB, false);
gpiod_set_value_cansleep(info->vbus_gpiod, 0); gpiod_set_value_cansleep(info->vbus_gpiod, 0);
ret = usb_role_switch_set_role(info->role_sw,
USB_ROLE_NONE);
if (ret)
dev_err(info->dev,
"failed to set none role: %d\n",
ret);
} }
} }
...@@ -194,6 +213,14 @@ static int ptn5150_init_dev_type(struct ptn5150_info *info) ...@@ -194,6 +213,14 @@ static int ptn5150_init_dev_type(struct ptn5150_info *info)
return 0; return 0;
} }
static void ptn5150_work_sync_and_put(void *data)
{
struct ptn5150_info *info = data;
cancel_work_sync(&info->irq_work);
usb_role_switch_put(info->role_sw);
}
static int ptn5150_i2c_probe(struct i2c_client *i2c) static int ptn5150_i2c_probe(struct i2c_client *i2c)
{ {
struct device *dev = &i2c->dev; struct device *dev = &i2c->dev;
...@@ -284,6 +311,15 @@ static int ptn5150_i2c_probe(struct i2c_client *i2c) ...@@ -284,6 +311,15 @@ static int ptn5150_i2c_probe(struct i2c_client *i2c)
if (ret) if (ret)
return -EINVAL; return -EINVAL;
info->role_sw = usb_role_switch_get(info->dev);
if (IS_ERR(info->role_sw))
return dev_err_probe(info->dev, PTR_ERR(info->role_sw),
"failed to get role switch\n");
ret = devm_add_action_or_reset(dev, ptn5150_work_sync_and_put, info);
if (ret)
return ret;
/* /*
* Update current extcon state if for example OTG connection was there * Update current extcon state if for example OTG connection was there
* before the probe * before the probe
......
...@@ -798,6 +798,7 @@ static const struct sm5502_type sm5504_data = { ...@@ -798,6 +798,7 @@ static const struct sm5502_type sm5504_data = {
static const struct of_device_id sm5502_dt_match[] = { static const struct of_device_id sm5502_dt_match[] = {
{ .compatible = "siliconmitus,sm5502-muic", .data = &sm5502_data }, { .compatible = "siliconmitus,sm5502-muic", .data = &sm5502_data },
{ .compatible = "siliconmitus,sm5504-muic", .data = &sm5504_data }, { .compatible = "siliconmitus,sm5504-muic", .data = &sm5504_data },
{ .compatible = "siliconmitus,sm5703-muic", .data = &sm5502_data },
{ }, { },
}; };
MODULE_DEVICE_TABLE(of, sm5502_dt_match); MODULE_DEVICE_TABLE(of, sm5502_dt_match);
...@@ -830,6 +831,7 @@ static SIMPLE_DEV_PM_OPS(sm5502_muic_pm_ops, ...@@ -830,6 +831,7 @@ static SIMPLE_DEV_PM_OPS(sm5502_muic_pm_ops,
static const struct i2c_device_id sm5502_i2c_id[] = { static const struct i2c_device_id sm5502_i2c_id[] = {
{ "sm5502", (kernel_ulong_t)&sm5502_data }, { "sm5502", (kernel_ulong_t)&sm5502_data },
{ "sm5504", (kernel_ulong_t)&sm5504_data }, { "sm5504", (kernel_ulong_t)&sm5504_data },
{ "sm5703-muic", (kernel_ulong_t)&sm5502_data },
{ } { }
}; };
MODULE_DEVICE_TABLE(i2c, sm5502_i2c_id); MODULE_DEVICE_TABLE(i2c, sm5502_i2c_id);
......
...@@ -226,16 +226,6 @@ static int usb_extcon_suspend(struct device *dev) ...@@ -226,16 +226,6 @@ static int usb_extcon_suspend(struct device *dev)
} }
} }
/*
* We don't want to process any IRQs after this point
* as GPIOs used behind I2C subsystem might not be
* accessible until resume completes. So disable IRQ.
*/
if (info->id_gpiod)
disable_irq(info->id_irq);
if (info->vbus_gpiod)
disable_irq(info->vbus_irq);
if (!device_may_wakeup(dev)) if (!device_may_wakeup(dev))
pinctrl_pm_select_sleep_state(dev); pinctrl_pm_select_sleep_state(dev);
...@@ -267,11 +257,6 @@ static int usb_extcon_resume(struct device *dev) ...@@ -267,11 +257,6 @@ static int usb_extcon_resume(struct device *dev)
} }
} }
if (info->id_gpiod)
enable_irq(info->id_irq);
if (info->vbus_gpiod)
enable_irq(info->vbus_irq);
queue_delayed_work(system_power_efficient_wq, queue_delayed_work(system_power_efficient_wq,
&info->wq_detcable, 0); &info->wq_detcable, 0);
......
...@@ -68,7 +68,7 @@ static int cros_ec_pd_command(struct cros_ec_extcon_info *info, ...@@ -68,7 +68,7 @@ static int cros_ec_pd_command(struct cros_ec_extcon_info *info,
struct cros_ec_command *msg; struct cros_ec_command *msg;
int ret; int ret;
msg = kzalloc(sizeof(*msg) + max(outsize, insize), GFP_KERNEL); msg = kzalloc(struct_size(msg, data, max(outsize, insize)), GFP_KERNEL);
if (!msg) if (!msg)
return -ENOMEM; return -ENOMEM;
......
...@@ -399,6 +399,7 @@ static ssize_t cable_state_show(struct device *dev, ...@@ -399,6 +399,7 @@ static ssize_t cable_state_show(struct device *dev,
/** /**
* extcon_sync() - Synchronize the state for an external connector. * extcon_sync() - Synchronize the state for an external connector.
* @edev: the extcon device * @edev: the extcon device
* @id: the unique id indicating an external connector
* *
* Note that this function send a notification in order to synchronize * Note that this function send a notification in order to synchronize
* the state and property of an external connector. * the state and property of an external connector.
...@@ -736,6 +737,9 @@ EXPORT_SYMBOL_GPL(extcon_set_property); ...@@ -736,6 +737,9 @@ EXPORT_SYMBOL_GPL(extcon_set_property);
/** /**
* extcon_set_property_sync() - Set property of an external connector with sync. * extcon_set_property_sync() - Set property of an external connector with sync.
* @edev: the extcon device
* @id: the unique id indicating an external connector
* @prop: the property id indicating an extcon property
* @prop_val: the pointer including the new value of extcon property * @prop_val: the pointer including the new value of extcon property
* *
* Note that when setting the property value of external connector, * Note that when setting the property value of external connector,
...@@ -851,6 +855,8 @@ EXPORT_SYMBOL_GPL(extcon_set_property_capability); ...@@ -851,6 +855,8 @@ EXPORT_SYMBOL_GPL(extcon_set_property_capability);
* @extcon_name: the extcon name provided with extcon_dev_register() * @extcon_name: the extcon name provided with extcon_dev_register()
* *
* Return the pointer of extcon device if success or ERR_PTR(err) if fail. * Return the pointer of extcon device if success or ERR_PTR(err) if fail.
* NOTE: This function returns -EPROBE_DEFER so it may only be called from
* probe() functions.
*/ */
struct extcon_dev *extcon_get_extcon_dev(const char *extcon_name) struct extcon_dev *extcon_get_extcon_dev(const char *extcon_name)
{ {
...@@ -864,7 +870,7 @@ struct extcon_dev *extcon_get_extcon_dev(const char *extcon_name) ...@@ -864,7 +870,7 @@ struct extcon_dev *extcon_get_extcon_dev(const char *extcon_name)
if (!strcmp(sd->name, extcon_name)) if (!strcmp(sd->name, extcon_name))
goto out; goto out;
} }
sd = NULL; sd = ERR_PTR(-EPROBE_DEFER);
out: out:
mutex_unlock(&extcon_dev_list_lock); mutex_unlock(&extcon_dev_list_lock);
return sd; return sd;
...@@ -1218,19 +1224,14 @@ int extcon_dev_register(struct extcon_dev *edev) ...@@ -1218,19 +1224,14 @@ int extcon_dev_register(struct extcon_dev *edev)
edev->dev.type = &edev->extcon_dev_type; edev->dev.type = &edev->extcon_dev_type;
} }
ret = device_register(&edev->dev);
if (ret) {
put_device(&edev->dev);
goto err_dev;
}
spin_lock_init(&edev->lock); spin_lock_init(&edev->lock);
edev->nh = devm_kcalloc(&edev->dev, edev->max_supported, if (edev->max_supported) {
sizeof(*edev->nh), GFP_KERNEL); edev->nh = kcalloc(edev->max_supported, sizeof(*edev->nh),
if (!edev->nh) { GFP_KERNEL);
ret = -ENOMEM; if (!edev->nh) {
device_unregister(&edev->dev); ret = -ENOMEM;
goto err_dev; goto err_alloc_nh;
}
} }
for (index = 0; index < edev->max_supported; index++) for (index = 0; index < edev->max_supported; index++)
...@@ -1241,6 +1242,12 @@ int extcon_dev_register(struct extcon_dev *edev) ...@@ -1241,6 +1242,12 @@ int extcon_dev_register(struct extcon_dev *edev)
dev_set_drvdata(&edev->dev, edev); dev_set_drvdata(&edev->dev, edev);
edev->state = 0; edev->state = 0;
ret = device_register(&edev->dev);
if (ret) {
put_device(&edev->dev);
goto err_dev;
}
mutex_lock(&extcon_dev_list_lock); mutex_lock(&extcon_dev_list_lock);
list_add(&edev->entry, &extcon_dev_list); list_add(&edev->entry, &extcon_dev_list);
mutex_unlock(&extcon_dev_list_lock); mutex_unlock(&extcon_dev_list_lock);
...@@ -1248,6 +1255,9 @@ int extcon_dev_register(struct extcon_dev *edev) ...@@ -1248,6 +1255,9 @@ int extcon_dev_register(struct extcon_dev *edev)
return 0; return 0;
err_dev: err_dev:
if (edev->max_supported)
kfree(edev->nh);
err_alloc_nh:
if (edev->max_supported) if (edev->max_supported)
kfree(edev->extcon_dev_type.groups); kfree(edev->extcon_dev_type.groups);
err_alloc_groups: err_alloc_groups:
...@@ -1308,6 +1318,7 @@ void extcon_dev_unregister(struct extcon_dev *edev) ...@@ -1308,6 +1318,7 @@ void extcon_dev_unregister(struct extcon_dev *edev)
if (edev->max_supported) { if (edev->max_supported) {
kfree(edev->extcon_dev_type.groups); kfree(edev->extcon_dev_type.groups);
kfree(edev->cables); kfree(edev->cables);
kfree(edev->nh);
} }
put_device(&edev->dev); put_device(&edev->dev);
......
...@@ -865,17 +865,20 @@ static int axp288_charger_probe(struct platform_device *pdev) ...@@ -865,17 +865,20 @@ static int axp288_charger_probe(struct platform_device *pdev)
info->regmap_irqc = axp20x->regmap_irqc; info->regmap_irqc = axp20x->regmap_irqc;
info->cable.edev = extcon_get_extcon_dev(AXP288_EXTCON_DEV_NAME); info->cable.edev = extcon_get_extcon_dev(AXP288_EXTCON_DEV_NAME);
if (info->cable.edev == NULL) { if (IS_ERR(info->cable.edev)) {
dev_dbg(dev, "%s is not ready, probe deferred\n", dev_err_probe(dev, PTR_ERR(info->cable.edev),
AXP288_EXTCON_DEV_NAME); "extcon_get_extcon_dev(%s) failed\n",
return -EPROBE_DEFER; AXP288_EXTCON_DEV_NAME);
return PTR_ERR(info->cable.edev);
} }
if (acpi_dev_present(USB_HOST_EXTCON_HID, NULL, -1)) { if (acpi_dev_present(USB_HOST_EXTCON_HID, NULL, -1)) {
info->otg.cable = extcon_get_extcon_dev(USB_HOST_EXTCON_NAME); info->otg.cable = extcon_get_extcon_dev(USB_HOST_EXTCON_NAME);
if (info->otg.cable == NULL) { if (IS_ERR(info->otg.cable)) {
dev_dbg(dev, "EXTCON_USB_HOST is not ready, probe deferred\n"); dev_err_probe(dev, PTR_ERR(info->otg.cable),
return -EPROBE_DEFER; "extcon_get_extcon_dev(%s) failed\n",
USB_HOST_EXTCON_NAME);
return PTR_ERR(info->otg.cable);
} }
dev_info(dev, "Using " USB_HOST_EXTCON_HID " extcon for usb-id\n"); dev_info(dev, "Using " USB_HOST_EXTCON_HID " extcon for usb-id\n");
} }
......
...@@ -985,13 +985,10 @@ static int charger_extcon_init(struct charger_manager *cm, ...@@ -985,13 +985,10 @@ static int charger_extcon_init(struct charger_manager *cm,
cable->nb.notifier_call = charger_extcon_notifier; cable->nb.notifier_call = charger_extcon_notifier;
cable->extcon_dev = extcon_get_extcon_dev(cable->extcon_name); cable->extcon_dev = extcon_get_extcon_dev(cable->extcon_name);
if (IS_ERR_OR_NULL(cable->extcon_dev)) { if (IS_ERR(cable->extcon_dev)) {
pr_err("Cannot find extcon_dev for %s (cable: %s)\n", pr_err("Cannot find extcon_dev for %s (cable: %s)\n",
cable->extcon_name, cable->name); cable->extcon_name, cable->name);
if (cable->extcon_dev == NULL) return PTR_ERR(cable->extcon_dev);
return -EPROBE_DEFER;
else
return PTR_ERR(cable->extcon_dev);
} }
for (i = 0; i < ARRAY_SIZE(extcon_mapping); i++) { for (i = 0; i < ARRAY_SIZE(extcon_mapping); i++) {
......
...@@ -242,10 +242,10 @@ static int max8997_battery_probe(struct platform_device *pdev) ...@@ -242,10 +242,10 @@ static int max8997_battery_probe(struct platform_device *pdev)
dev_info(&pdev->dev, "couldn't get charger regulator\n"); dev_info(&pdev->dev, "couldn't get charger regulator\n");
} }
charger->edev = extcon_get_extcon_dev("max8997-muic"); charger->edev = extcon_get_extcon_dev("max8997-muic");
if (IS_ERR_OR_NULL(charger->edev)) { if (IS_ERR(charger->edev)) {
if (!charger->edev) dev_err_probe(charger->dev, PTR_ERR(charger->edev),
return -EPROBE_DEFER; "couldn't get extcon device: max8997-muic\n");
dev_info(charger->dev, "couldn't get extcon device\n"); return PTR_ERR(charger->edev);
} }
if (!IS_ERR(charger->reg) && !IS_ERR_OR_NULL(charger->edev)) { if (!IS_ERR(charger->reg) && !IS_ERR_OR_NULL(charger->edev)) {
......
...@@ -455,13 +455,8 @@ static struct extcon_dev *dwc3_get_extcon(struct dwc3 *dwc) ...@@ -455,13 +455,8 @@ static struct extcon_dev *dwc3_get_extcon(struct dwc3 *dwc)
* This device property is for kernel internal use only and * This device property is for kernel internal use only and
* is expected to be set by the glue code. * is expected to be set by the glue code.
*/ */
if (device_property_read_string(dev, "linux,extcon-name", &name) == 0) { if (device_property_read_string(dev, "linux,extcon-name", &name) == 0)
edev = extcon_get_extcon_dev(name); return extcon_get_extcon_dev(name);
if (!edev)
return ERR_PTR(-EPROBE_DEFER);
return edev;
}
/* /*
* Try to get an extcon device from the USB PHY controller's "port" * Try to get an extcon device from the USB PHY controller's "port"
......
...@@ -95,8 +95,8 @@ static int omap_otg_probe(struct platform_device *pdev) ...@@ -95,8 +95,8 @@ static int omap_otg_probe(struct platform_device *pdev)
return -ENODEV; return -ENODEV;
extcon = extcon_get_extcon_dev(config->extcon); extcon = extcon_get_extcon_dev(config->extcon);
if (!extcon) if (IS_ERR(extcon))
return -EPROBE_DEFER; return PTR_ERR(extcon);
otg_dev = devm_kzalloc(&pdev->dev, sizeof(*otg_dev), GFP_KERNEL); otg_dev = devm_kzalloc(&pdev->dev, sizeof(*otg_dev), GFP_KERNEL);
if (!otg_dev) if (!otg_dev)
......
...@@ -1708,8 +1708,8 @@ static int fusb302_probe(struct i2c_client *client, ...@@ -1708,8 +1708,8 @@ static int fusb302_probe(struct i2c_client *client,
*/ */
if (device_property_read_string(dev, "linux,extcon-name", &name) == 0) { if (device_property_read_string(dev, "linux,extcon-name", &name) == 0) {
chip->extcon = extcon_get_extcon_dev(name); chip->extcon = extcon_get_extcon_dev(name);
if (!chip->extcon) if (IS_ERR(chip->extcon))
return -EPROBE_DEFER; return PTR_ERR(chip->extcon);
} }
chip->vbus = devm_regulator_get(chip->dev, "vbus"); chip->vbus = devm_regulator_get(chip->dev, "vbus");
......
...@@ -296,7 +296,7 @@ static inline void devm_extcon_unregister_notifier_all(struct device *dev, ...@@ -296,7 +296,7 @@ static inline void devm_extcon_unregister_notifier_all(struct device *dev,
static inline struct extcon_dev *extcon_get_extcon_dev(const char *extcon_name) static inline struct extcon_dev *extcon_get_extcon_dev(const char *extcon_name)
{ {
return ERR_PTR(-ENODEV); return NULL;
} }
static inline struct extcon_dev *extcon_find_edev_by_node(struct device_node *node) static inline struct extcon_dev *extcon_find_edev_by_node(struct device_node *node)
......
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