Hi Chanwoo,

On 03/17/2016 02:07 PM, Chanwoo Choi wrote:
> Hi Lu,
>
> To handle extcon (external connector), I implemented the unique id
> for each external connector on patch[1] instead of using the ambiguous string 
> type. 
> [1] 2a9de9c0f08d6 (extcon: Use the unique id for external connector instead 
> of string)
>
> So I recommend that you should use the unique id (ex. EXTCON_USB, 
> EXTCON_USB_HOST)
> with extcon_register_notifier(), extcon_get_cable_state_() and 
> extcon_set_cable_state_().
>
> extcon_register_interest() is deprecated-> extcon_register_notifier()
> extcon_get_cable_state() is deprecated -> extcon_get_cable_state_()
> extcon_set_cable_state() is deprecated -> extcon_set_cable_state_()

Sure. I will use the new interfaces with a refreshed patch serial later.

>
>
> You can refer to usage for new function with unique id on patch[2]
> [2] 5960387a2fb83 (usb: dwc3: omap: Replace deprecated API of extcon)

Thanks. That's helpful.

By the way, is extcon_get_extcon_dev() still available?

>
> I'm sorry for late reply. I add the some comment on below.

Never mind. Thank you for reminding me.

Best regards,
Baolu

>
>
> On 2016년 03월 17일 14:46, Lu Baolu wrote:
>> Several Intel PCHs and SOCs have an internal mux that is used to
>> share one USB port between device controller and host controller.
>>
>> A usb port mux could be abstracted as the following elements:
>> 1) mux state: HOST or PERIPHERAL;
>> 2) an extcon cable which triggers the change of mux state between
>>    HOST and PERIPHERAL;
>> 3) The required action to do the real port switch.
>>
>> This patch adds the common code to handle usb port mux. With this
>> common code, the individual mux driver, which always is platform
>> dependent, could focus on the real operation of mux switch.
>>
>> Signed-off-by: Lu Baolu <baolu...@linux.intel.com>
>> Reviewed-by: Heikki Krogerus <heikki.kroge...@linux.intel.com>
>> Reviewed-by: Felipe Balbi <ba...@kernel.org>
>> ---
>>  Documentation/ABI/testing/sysfs-bus-platform |  15 +++
>>  MAINTAINERS                                  |   7 ++
>>  drivers/usb/Kconfig                          |   2 +
>>  drivers/usb/Makefile                         |   1 +
>>  drivers/usb/mux/Kconfig                      |  12 ++
>>  drivers/usb/mux/Makefile                     |   4 +
>>  drivers/usb/mux/intel-mux.c                  | 180 
>> +++++++++++++++++++++++++++
>>  include/linux/usb/intel-mux.h                |  43 +++++++
>>  8 files changed, 264 insertions(+)
>>  create mode 100644 drivers/usb/mux/Kconfig
>>  create mode 100644 drivers/usb/mux/Makefile
>>  create mode 100644 drivers/usb/mux/intel-mux.c
>>  create mode 100644 include/linux/usb/intel-mux.h
>>
>> diff --git a/Documentation/ABI/testing/sysfs-bus-platform 
>> b/Documentation/ABI/testing/sysfs-bus-platform
>> index 5172a61..23bf76e 100644
>> --- a/Documentation/ABI/testing/sysfs-bus-platform
>> +++ b/Documentation/ABI/testing/sysfs-bus-platform
>> @@ -18,3 +18,18 @@ Description:
>>              devices to opt-out of driver binding using a driver_override
>>              name such as "none".  Only a single driver may be specified in
>>              the override, there is no support for parsing delimiters.
>> +
>> +What:               /sys/bus/platform/devices/.../port_mux
>> +Date:               Febuary 2016
>> +Contact:    Lu Baolu <baolu...@linux.intel.com>
>> +Description:
>> +            In some platforms, a single USB port is shared between a USB 
>> host
>> +            controller and a device controller. A USB mux driver is needed 
>> to
>> +            handle the port mux. port_mux attribute shows and stores the mux
>> +            state.
>> +            For read:
>> +            'peripheral' - mux switched to PERIPHERAL controller;
>> +            'host'       - mux switched to HOST controller.
>> +            For write:
>> +            'peripheral' - mux will be switched to PERIPHERAL controller;
>> +            'host'       - mux will be switched to HOST controller.
>> diff --git a/MAINTAINERS b/MAINTAINERS
>> index da3e4d8..0dbee11 100644
>> --- a/MAINTAINERS
>> +++ b/MAINTAINERS
>> @@ -11399,6 +11399,13 @@ T:  git 
>> git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb.git
>>  S:  Maintained
>>  F:  drivers/usb/phy/
>>  
>> +USB PORT MUX DRIVER
>> +M:  Lu Baolu <baolu...@linux.intel.com>
>> +L:  linux-usb@vger.kernel.org
>> +S:  Supported
>> +F:  include/linux/usb/intel-mux.h
>> +F:  drivers/usb/mux/intel-mux.c
>> +
>>  USB PRINTER DRIVER (usblp)
>>  M:  Pete Zaitcev <zait...@redhat.com>
>>  L:  linux-usb@vger.kernel.org
>> diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig
>> index 8ed451d..dbd6620 100644
>> --- a/drivers/usb/Kconfig
>> +++ b/drivers/usb/Kconfig
>> @@ -149,6 +149,8 @@ endif # USB
>>  
>>  source "drivers/usb/phy/Kconfig"
>>  
>> +source "drivers/usb/mux/Kconfig"
>> +
>>  source "drivers/usb/gadget/Kconfig"
>>  
>>  config USB_LED_TRIG
>> diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile
>> index d5c57f1..6433f0c 100644
>> --- a/drivers/usb/Makefile
>> +++ b/drivers/usb/Makefile
>> @@ -6,6 +6,7 @@
>>  
>>  obj-$(CONFIG_USB)           += core/
>>  obj-$(CONFIG_USB_SUPPORT)   += phy/
>> +obj-$(CONFIG_USB_SUPPORT)   += mux/
>>  
>>  obj-$(CONFIG_USB_DWC3)              += dwc3/
>>  obj-$(CONFIG_USB_DWC2)              += dwc2/
>> diff --git a/drivers/usb/mux/Kconfig b/drivers/usb/mux/Kconfig
>> new file mode 100644
>> index 0000000..62e2cc3
>> --- /dev/null
>> +++ b/drivers/usb/mux/Kconfig
>> @@ -0,0 +1,12 @@
>> +#
>> +# USB port mux driver configuration
>> +#
>> +menu "USB Port MUX drivers"
>> +config INTEL_USB_MUX
>> +    select EXTCON
>> +    def_bool n
>> +    help
>> +      Common code for all Intel dual role port mux drivers. All Intel
>> +      usb port mux drivers should select it.
>> +
>> +endmenu
>> diff --git a/drivers/usb/mux/Makefile b/drivers/usb/mux/Makefile
>> new file mode 100644
>> index 0000000..84f0ae8
>> --- /dev/null
>> +++ b/drivers/usb/mux/Makefile
>> @@ -0,0 +1,4 @@
>> +#
>> +# Makefile for USB port mux drivers
>> +#
>> +obj-$(CONFIG_INTEL_USB_MUX)         += intel-mux.o
>> diff --git a/drivers/usb/mux/intel-mux.c b/drivers/usb/mux/intel-mux.c
>> new file mode 100644
>> index 0000000..bb7b192
>> --- /dev/null
>> +++ b/drivers/usb/mux/intel-mux.c
>> @@ -0,0 +1,180 @@
>> +/**
>> + * intel_mux.c - USB Port Mux support
>> + *
>> + * Copyright (C) 2016 Intel Corporation
>> + *
>> + * Author: Lu Baolu <baolu...@linux.intel.com>
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License version 2 as
>> + * published by the Free Software Foundation.
>> + */
>> +#include <linux/slab.h>
>> +#include <linux/notifier.h>
>> +#include <linux/extcon.h>
>> +#include <linux/err.h>
>> +
>> +struct intel_usb_mux {
>> +    struct device   *dev;
>> +    char            *cable_name;
>> +    int             (*cable_set_cb)(struct device *dev);
>> +    int             (*cable_unset_cb)(struct device *dev);
>> +
>> +    struct notifier_block           nb;
>> +    struct extcon_specific_cable_nb obj;
>> +
>> +    /*
>> +     * The state of the mux.
>> +     * 0, 1 - mux switch state
>> +     * -1   - uninitialized state
>> +     */
>> +    int                             mux_state;
>> +
>> +     /* lock for mux_state */
>> +    struct mutex                    mux_mutex;
>> +};
>> +
>> +static int usb_mux_change_state(struct intel_usb_mux *mux, int state)
>> +{
>> +    int ret;
>> +    struct device *dev = mux->dev;
>> +
>> +    dev_WARN_ONCE(dev,
>> +                  !mutex_is_locked(&mux->mux_mutex),
>> +                  "mutex is unlocked\n");
>> +
>> +    mux->mux_state = state;
>> +
>> +    if (mux->mux_state)
>> +            ret = mux->cable_set_cb(dev);
>> +    else
>> +            ret = mux->cable_unset_cb(dev);
>> +
>> +    return ret;
>> +}
>> +
>> +static int usb_mux_notifier(struct notifier_block *nb,
>> +                        unsigned long event, void *ptr)
>> +{
>> +    struct intel_usb_mux *mux;
>> +    int state;
>> +    int ret = NOTIFY_DONE;
>> +
>> +    mux = container_of(nb, struct intel_usb_mux, nb);
>> +
>> +    state = extcon_get_cable_state(mux->obj.edev,
>> +                                   mux->cable_name);
> Use the extcon_get_cable_stet_().
>
>> +
>> +    if (mux->mux_state == -1 || mux->mux_state != state) {
>> +            mutex_lock(&mux->mux_mutex);
>> +            ret = usb_mux_change_state(mux, state);
>> +            mutex_unlock(&mux->mux_mutex);
>> +    }
>> +
>> +    return ret;
>> +}
>> +
>> +static ssize_t port_mux_show(struct device *dev,
>> +                         struct device_attribute *attr, char *buf)
>> +{
>> +    struct intel_usb_mux *mux = dev_get_drvdata(dev);
>> +
>> +    if (dev_WARN_ONCE(dev, !mux, "mux without data structure\n"))
>> +            return 0;
>> +
>> +    return sprintf(buf, "%s\n", mux->mux_state ? "host" : "peripheral");
>> +}
>> +
>> +static ssize_t port_mux_store(struct device *dev,
>> +                          struct device_attribute *attr,
>> +                          const char *buf, size_t count)
>> +{
>> +    struct intel_usb_mux *mux = dev_get_drvdata(dev);
>> +    int state;
>> +
>> +    if (dev_WARN_ONCE(dev, !mux, "mux without data structure\n"))
>> +            return -EINVAL;
>> +
>> +    if (sysfs_streq(buf, "peripheral"))
>> +            state = 0;
>> +    else if (sysfs_streq(buf, "host"))
>> +            state = 1;
>> +    else
>> +            return -EINVAL;
>> +
>> +    mutex_lock(&mux->mux_mutex);
>> +    usb_mux_change_state(mux, state);
>> +    mutex_unlock(&mux->mux_mutex);
>> +
>> +    return count;
>> +}
>> +static DEVICE_ATTR_RW(port_mux);
>> +
>> +int intel_usb_mux_bind_cable(struct device *dev,
>> +                         char *extcon_name,
>> +                         char *cable_name,
>> +                         int (*cable_set_cb)(struct device *dev),
>> +                         int (*cable_unset_cb)(struct device *dev))
>> +{
>> +    int ret;
>> +    struct intel_usb_mux *mux;
>> +
>> +    if (!cable_name)
>> +            return -ENODEV;
>> +
>> +    mux = devm_kzalloc(dev, sizeof(*mux), GFP_KERNEL);
>> +    if (!mux)
>> +            return -ENOMEM;
>> +
>> +    mux->dev = dev;
>> +    mux->cable_name = kstrdup(cable_name, GFP_KERNEL);
>> +    mux->cable_set_cb = cable_set_cb;
>> +    mux->cable_unset_cb = cable_unset_cb;
>> +    mux->nb.notifier_call = usb_mux_notifier;
>> +    mutex_init(&mux->mux_mutex);
>> +    mux->mux_state = -1;
>> +    dev_set_drvdata(dev, mux);
>> +    ret = extcon_register_interest(&mux->obj, extcon_name,
>> +                                   cable_name, &mux->nb);
> Use the extcon_register_notifier()
>
>> +    if (ret) {
>> +            kfree(mux->cable_name);
>> +            dev_err(dev, "failed to register extcon notifier\n");
>> +            return -ENODEV;
>> +    }
>> +
>> +    usb_mux_notifier(&mux->nb, 0, NULL);
>> +
>> +    /* register the sysfs interface */
>> +    ret = device_create_file(dev, &dev_attr_port_mux);
>> +    if (ret) {
>> +            extcon_unregister_interest(&mux->obj);
> Use the extcon_unregister_notifier()
>
>> +            kfree(mux->cable_name);
>> +            dev_err(dev, "failed to create sysfs attribute\n");
>> +            return -ENODEV;
>> +    }
>> +
>> +    return 0;
>> +}
>> +EXPORT_SYMBOL_GPL(intel_usb_mux_bind_cable);
>> +
>> +int intel_usb_mux_unbind_cable(struct device *dev)
>> +{
>> +    struct intel_usb_mux *mux = dev_get_drvdata(dev);
>> +
>> +    device_remove_file(dev, &dev_attr_port_mux);
>> +    extcon_unregister_interest(&mux->obj);
> Use the extcon_unregister_notifier()
>
>> +    kfree(mux->cable_name);
>> +
>> +    return 0;
>> +}
>> +EXPORT_SYMBOL_GPL(intel_usb_mux_unbind_cable);
>> +
>> +#ifdef CONFIG_PM_SLEEP
>> +void intel_usb_mux_complete(struct device *dev)
>> +{
>> +    struct intel_usb_mux *mux = dev_get_drvdata(dev);
>> +
>> +    usb_mux_notifier(&mux->nb, 0, NULL);
>> +}
>> +EXPORT_SYMBOL_GPL(intel_usb_mux_complete);
>> +#endif
>> diff --git a/include/linux/usb/intel-mux.h b/include/linux/usb/intel-mux.h
>> new file mode 100644
>> index 0000000..fd5612d
>> --- /dev/null
>> +++ b/include/linux/usb/intel-mux.h
>> @@ -0,0 +1,43 @@
>> +/**
>> + * intel_mux.h - USB Port Mux definitions
>> + *
>> + * Copyright (C) 2016 Intel Corporation
>> + *
>> + * Author: Lu Baolu <baolu...@linux.intel.com>
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License version 2 as
>> + * published by the Free Software Foundation.
>> + */
>> +
>> +#ifndef __LINUX_USB_INTEL_MUX_H
>> +#define __LINUX_USB_INTEL_MUX_H
>> +
>> +#if IS_ENABLED(CONFIG_INTEL_USB_MUX)
>> +int intel_usb_mux_bind_cable(struct device *dev, char *extcon_name,
>> +                         char *cable_name,
>> +                         int (*cable_set_cb)(struct device *dev),
>> +                         int (*cable_unset_cb)(struct device *dev));
>> +int intel_usb_mux_unbind_cable(struct device *dev);
>> +#ifdef CONFIG_PM_SLEEP
>> +void intel_usb_mux_complete(struct device *dev);
>> +#endif
>> +
>> +#else
>> +static inline int
>> +intel_usb_mux_bind_cable(struct device *dev,
>> +                     char *extcon_name,
>> +                     char *cable_name,
>> +                     int (*cable_set_cb)(struct device *dev),
>> +                     int (*cable_unset_cb)(struct device *dev))
>> +{
>> +    return -ENODEV;
>> +}
>> +
>> +static inline int intel_usb_mux_unbind_cable(struct device *dev)
>> +{
>> +    return 0;
>> +}
>> +#endif /* CONFIG_INTEL_USB_MUX */
>> +
>> +#endif /* __LINUX_USB_INTEL_MUX_H */
>>
> Best Regards,
> Chanwoo Choi
>

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to