Commit 9f57ed09 authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

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

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

Chanwoo writes:

Update extcon for 4.14

Detailed description for this pull request:
1. Add new 'extcon-usbc-cros-ec.c' driver
- ChromeOS Embedded Controller extcon driver supports
  the detection of the Display Port (EXTCON_DISP_DP)
  through USB C-type and contol it.

2. Update extcon core
- Modify the description for both functions and structures
  in order to improve the readability and give the more correct
  guide about the role of functions because there are different
  explanation even if the same arguments.

- Keep the indentation with tab instead of space

- Remove the following deprecated extcon API. The deprecated API
  are exchanged on all of linux tree.
  : extcon_get_cable_state_() -> extcon_get_state()
  : extcon_set_cable_state_() -> extcon_set_state_sync()

3. Include the two immutable branch as following:
- ib-extcon-mfd-4.14 for the 'extcon-ubsc-cros-ec.c' driver
  because the patches of 'extcon-ubsc-cros-ec.c' touch the MFD directory.
- ib-extcon-usb-phy-4.14 for removing the deprecated extcon API
  because the usb/phy driver usese the deprecated extcon API.
  So, this immutable branch alters the extcon API and then
  remove them from extcon.

4. Fix minor issue of extcon driver
- Fix the MHL detection on extcon-max77693.c
- Convert to using %pOF instead of full_name on extcon.c
- Add 'const' kerywod for acpi_device_id on extcon-intel-int3496.c
parents 981b4677 4243c408
ChromeOS EC USB Type-C cable and accessories detection
On ChromeOS systems with USB Type C ports, the ChromeOS Embedded Controller is
able to detect the state of external accessories such as display adapters
or USB devices when said accessories are attached or detached.
The node for this device must be under a cros-ec node like google,cros-ec-spi
or google,cros-ec-i2c.
Required properties:
- compatible: Should be "google,extcon-usbc-cros-ec".
- google,usb-port-id: Specifies the USB port ID to use.
Example:
cros-ec@0 {
compatible = "google,cros-ec-i2c";
...
extcon {
compatible = "google,extcon-usbc-cros-ec";
google,usb-port-id = <0>;
};
}
...@@ -150,4 +150,11 @@ config EXTCON_USB_GPIO ...@@ -150,4 +150,11 @@ config EXTCON_USB_GPIO
Say Y here to enable GPIO based USB cable detection extcon support. Say Y here to enable GPIO based USB cable detection extcon support.
Used typically if GPIO is used for USB ID pin detection. Used typically if GPIO is used for USB ID pin detection.
config EXTCON_USBC_CROS_EC
tristate "ChromeOS Embedded Controller EXTCON support"
depends on MFD_CROS_EC
help
Say Y here to enable USB Type C cable detection extcon support when
using Chrome OS EC based USB Type-C ports.
endif endif
...@@ -20,3 +20,4 @@ obj-$(CONFIG_EXTCON_QCOM_SPMI_MISC) += extcon-qcom-spmi-misc.o ...@@ -20,3 +20,4 @@ obj-$(CONFIG_EXTCON_QCOM_SPMI_MISC) += extcon-qcom-spmi-misc.o
obj-$(CONFIG_EXTCON_RT8973A) += extcon-rt8973a.o obj-$(CONFIG_EXTCON_RT8973A) += extcon-rt8973a.o
obj-$(CONFIG_EXTCON_SM5502) += extcon-sm5502.o obj-$(CONFIG_EXTCON_SM5502) += extcon-sm5502.o
obj-$(CONFIG_EXTCON_USB_GPIO) += extcon-usb-gpio.o obj-$(CONFIG_EXTCON_USB_GPIO) += extcon-usb-gpio.o
obj-$(CONFIG_EXTCON_USBC_CROS_EC) += extcon-usbc-cros-ec.o
...@@ -59,10 +59,9 @@ static void devm_extcon_dev_notifier_all_unreg(struct device *dev, void *res) ...@@ -59,10 +59,9 @@ static void devm_extcon_dev_notifier_all_unreg(struct device *dev, void *res)
/** /**
* devm_extcon_dev_allocate - Allocate managed extcon device * devm_extcon_dev_allocate - Allocate managed extcon device
* @dev: device owning the extcon device being created * @dev: the device owning the extcon device being created
* @supported_cable: Array of supported extcon ending with EXTCON_NONE. * @supported_cable: the array of the supported external connectors
* If supported_cable is NULL, cable name related APIs * ending with EXTCON_NONE.
* are disabled.
* *
* This function manages automatically the memory of extcon device using device * This function manages automatically the memory of extcon device using device
* resource management and simplify the control of freeing the memory of extcon * resource management and simplify the control of freeing the memory of extcon
...@@ -97,8 +96,8 @@ EXPORT_SYMBOL_GPL(devm_extcon_dev_allocate); ...@@ -97,8 +96,8 @@ EXPORT_SYMBOL_GPL(devm_extcon_dev_allocate);
/** /**
* devm_extcon_dev_free() - Resource-managed extcon_dev_unregister() * devm_extcon_dev_free() - Resource-managed extcon_dev_unregister()
* @dev: device the extcon belongs to * @dev: the device owning the extcon device being created
* @edev: the extcon device to unregister * @edev: the extcon device to be freed
* *
* Free the memory that is allocated with devm_extcon_dev_allocate() * Free the memory that is allocated with devm_extcon_dev_allocate()
* function. * function.
...@@ -112,10 +111,9 @@ EXPORT_SYMBOL_GPL(devm_extcon_dev_free); ...@@ -112,10 +111,9 @@ EXPORT_SYMBOL_GPL(devm_extcon_dev_free);
/** /**
* devm_extcon_dev_register() - Resource-managed extcon_dev_register() * devm_extcon_dev_register() - Resource-managed extcon_dev_register()
* @dev: device to allocate extcon device * @dev: the device owning the extcon device being created
* @edev: the new extcon device to register * @edev: the extcon device to be registered
* *
* Managed extcon_dev_register() function. If extcon device is attached with
* this function, that extcon device is automatically unregistered on driver * this function, that extcon device is automatically unregistered on driver
* detach. Internally this function calls extcon_dev_register() function. * detach. Internally this function calls extcon_dev_register() function.
* To get more information, refer that function. * To get more information, refer that function.
...@@ -149,8 +147,8 @@ EXPORT_SYMBOL_GPL(devm_extcon_dev_register); ...@@ -149,8 +147,8 @@ EXPORT_SYMBOL_GPL(devm_extcon_dev_register);
/** /**
* devm_extcon_dev_unregister() - Resource-managed extcon_dev_unregister() * devm_extcon_dev_unregister() - Resource-managed extcon_dev_unregister()
* @dev: device the extcon belongs to * @dev: the device owning the extcon device being created
* @edev: the extcon device to unregister * @edev: the extcon device to unregistered
* *
* Unregister extcon device that is registered with devm_extcon_dev_register() * Unregister extcon device that is registered with devm_extcon_dev_register()
* function. * function.
...@@ -164,10 +162,10 @@ EXPORT_SYMBOL_GPL(devm_extcon_dev_unregister); ...@@ -164,10 +162,10 @@ EXPORT_SYMBOL_GPL(devm_extcon_dev_unregister);
/** /**
* devm_extcon_register_notifier() - Resource-managed extcon_register_notifier() * devm_extcon_register_notifier() - Resource-managed extcon_register_notifier()
* @dev: device to allocate extcon device * @dev: the device owning the extcon device being created
* @edev: the extcon device that has the external connecotr. * @edev: the extcon device
* @id: the unique id of each external connector in extcon enumeration. * @id: the unique id among the extcon enumeration
* @nb: a notifier block to be registered. * @nb: a notifier block to be registered
* *
* This function manages automatically the notifier of extcon device using * This function manages automatically the notifier of extcon device using
* device resource management and simplify the control of unregistering * device resource management and simplify the control of unregistering
...@@ -208,10 +206,10 @@ EXPORT_SYMBOL(devm_extcon_register_notifier); ...@@ -208,10 +206,10 @@ EXPORT_SYMBOL(devm_extcon_register_notifier);
/** /**
* devm_extcon_unregister_notifier() * devm_extcon_unregister_notifier()
- Resource-managed extcon_unregister_notifier() - Resource-managed extcon_unregister_notifier()
* @dev: device to allocate extcon device * @dev: the device owning the extcon device being created
* @edev: the extcon device that has the external connecotr. * @edev: the extcon device
* @id: the unique id of each external connector in extcon enumeration. * @id: the unique id among the extcon enumeration
* @nb: a notifier block to be registered. * @nb: a notifier block to be registered
*/ */
void devm_extcon_unregister_notifier(struct device *dev, void devm_extcon_unregister_notifier(struct device *dev,
struct extcon_dev *edev, unsigned int id, struct extcon_dev *edev, unsigned int id,
...@@ -225,9 +223,9 @@ EXPORT_SYMBOL(devm_extcon_unregister_notifier); ...@@ -225,9 +223,9 @@ EXPORT_SYMBOL(devm_extcon_unregister_notifier);
/** /**
* devm_extcon_register_notifier_all() * devm_extcon_register_notifier_all()
* - Resource-managed extcon_register_notifier_all() * - Resource-managed extcon_register_notifier_all()
* @dev: device to allocate extcon device * @dev: the device owning the extcon device being created
* @edev: the extcon device that has the external connecotr. * @edev: the extcon device
* @nb: a notifier block to be registered. * @nb: a notifier block to be registered
* *
* This function manages automatically the notifier of extcon device using * This function manages automatically the notifier of extcon device using
* device resource management and simplify the control of unregistering * device resource management and simplify the control of unregistering
...@@ -263,9 +261,9 @@ EXPORT_SYMBOL(devm_extcon_register_notifier_all); ...@@ -263,9 +261,9 @@ EXPORT_SYMBOL(devm_extcon_register_notifier_all);
/** /**
* devm_extcon_unregister_notifier_all() * devm_extcon_unregister_notifier_all()
* - Resource-managed extcon_unregister_notifier_all() * - Resource-managed extcon_unregister_notifier_all()
* @dev: device to allocate extcon device * @dev: the device owning the extcon device being created
* @edev: the extcon device that has the external connecotr. * @edev: the extcon device
* @nb: a notifier block to be registered. * @nb: a notifier block to be registered
*/ */
void devm_extcon_unregister_notifier_all(struct device *dev, void devm_extcon_unregister_notifier_all(struct device *dev,
struct extcon_dev *edev, struct extcon_dev *edev,
......
...@@ -171,7 +171,7 @@ static int int3496_remove(struct platform_device *pdev) ...@@ -171,7 +171,7 @@ static int int3496_remove(struct platform_device *pdev)
return 0; return 0;
} }
static struct acpi_device_id int3496_acpi_match[] = { static const struct acpi_device_id int3496_acpi_match[] = {
{ "INT3496" }, { "INT3496" },
{ } { }
}; };
......
...@@ -811,9 +811,8 @@ static int max77693_muic_chg_handler(struct max77693_muic_info *info) ...@@ -811,9 +811,8 @@ static int max77693_muic_chg_handler(struct max77693_muic_info *info)
*/ */
extcon_set_state_sync(info->edev, EXTCON_CHG_USB_DCP, extcon_set_state_sync(info->edev, EXTCON_CHG_USB_DCP,
attached); attached);
if (!cable_attached) extcon_set_state_sync(info->edev, EXTCON_DISP_MHL,
extcon_set_state_sync(info->edev, cable_attached);
EXTCON_DISP_MHL, cable_attached);
break; break;
} }
......
/**
* drivers/extcon/extcon-usbc-cros-ec - ChromeOS Embedded Controller extcon
*
* Copyright (C) 2017 Google, Inc
* Author: Benson Leung <bleung@chromium.org>
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <linux/extcon.h>
#include <linux/kernel.h>
#include <linux/mfd/cros_ec.h>
#include <linux/module.h>
#include <linux/notifier.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/sched.h>
struct cros_ec_extcon_info {
struct device *dev;
struct extcon_dev *edev;
int port_id;
struct cros_ec_device *ec;
struct notifier_block notifier;
bool dp; /* DisplayPort enabled */
bool mux; /* SuperSpeed (usb3) enabled */
unsigned int power_type;
};
static const unsigned int usb_type_c_cable[] = {
EXTCON_DISP_DP,
EXTCON_NONE,
};
/**
* cros_ec_pd_command() - Send a command to the EC.
* @info: pointer to struct cros_ec_extcon_info
* @command: EC command
* @version: EC command version
* @outdata: EC command output data
* @outsize: Size of outdata
* @indata: EC command input data
* @insize: Size of indata
*
* Return: 0 on success, <0 on failure.
*/
static int cros_ec_pd_command(struct cros_ec_extcon_info *info,
unsigned int command,
unsigned int version,
void *outdata,
unsigned int outsize,
void *indata,
unsigned int insize)
{
struct cros_ec_command *msg;
int ret;
msg = kzalloc(sizeof(*msg) + max(outsize, insize), GFP_KERNEL);
if (!msg)
return -ENOMEM;
msg->version = version;
msg->command = command;
msg->outsize = outsize;
msg->insize = insize;
if (outsize)
memcpy(msg->data, outdata, outsize);
ret = cros_ec_cmd_xfer_status(info->ec, msg);
if (ret >= 0 && insize)
memcpy(indata, msg->data, insize);
kfree(msg);
return ret;
}
/**
* cros_ec_usb_get_power_type() - Get power type info about PD device attached
* to given port.
* @info: pointer to struct cros_ec_extcon_info
*
* Return: power type on success, <0 on failure.
*/
static int cros_ec_usb_get_power_type(struct cros_ec_extcon_info *info)
{
struct ec_params_usb_pd_power_info req;
struct ec_response_usb_pd_power_info resp;
int ret;
req.port = info->port_id;
ret = cros_ec_pd_command(info, EC_CMD_USB_PD_POWER_INFO, 0,
&req, sizeof(req), &resp, sizeof(resp));
if (ret < 0)
return ret;
return resp.type;
}
/**
* cros_ec_usb_get_pd_mux_state() - Get PD mux state for given port.
* @info: pointer to struct cros_ec_extcon_info
*
* Return: PD mux state on success, <0 on failure.
*/
static int cros_ec_usb_get_pd_mux_state(struct cros_ec_extcon_info *info)
{
struct ec_params_usb_pd_mux_info req;
struct ec_response_usb_pd_mux_info resp;
int ret;
req.port = info->port_id;
ret = cros_ec_pd_command(info, EC_CMD_USB_PD_MUX_INFO, 0,
&req, sizeof(req),
&resp, sizeof(resp));
if (ret < 0)
return ret;
return resp.flags;
}
/**
* cros_ec_usb_get_role() - Get role info about possible PD device attached to a
* given port.
* @info: pointer to struct cros_ec_extcon_info
* @polarity: pointer to cable polarity (return value)
*
* Return: role info on success, -ENOTCONN if no cable is connected, <0 on
* failure.
*/
static int cros_ec_usb_get_role(struct cros_ec_extcon_info *info,
bool *polarity)
{
struct ec_params_usb_pd_control pd_control;
struct ec_response_usb_pd_control_v1 resp;
int ret;
pd_control.port = info->port_id;
pd_control.role = USB_PD_CTRL_ROLE_NO_CHANGE;
pd_control.mux = USB_PD_CTRL_MUX_NO_CHANGE;
ret = cros_ec_pd_command(info, EC_CMD_USB_PD_CONTROL, 1,
&pd_control, sizeof(pd_control),
&resp, sizeof(resp));
if (ret < 0)
return ret;
if (!(resp.enabled & PD_CTRL_RESP_ENABLED_CONNECTED))
return -ENOTCONN;
*polarity = resp.polarity;
return resp.role;
}
/**
* cros_ec_pd_get_num_ports() - Get number of EC charge ports.
* @info: pointer to struct cros_ec_extcon_info
*
* Return: number of ports on success, <0 on failure.
*/
static int cros_ec_pd_get_num_ports(struct cros_ec_extcon_info *info)
{
struct ec_response_usb_pd_ports resp;
int ret;
ret = cros_ec_pd_command(info, EC_CMD_USB_PD_PORTS,
0, NULL, 0, &resp, sizeof(resp));
if (ret < 0)
return ret;
return resp.num_ports;
}
static int extcon_cros_ec_detect_cable(struct cros_ec_extcon_info *info,
bool force)
{
struct device *dev = info->dev;
int role, power_type;
bool polarity = false;
bool dp = false;
bool mux = false;
bool hpd = false;
power_type = cros_ec_usb_get_power_type(info);
if (power_type < 0) {
dev_err(dev, "failed getting power type err = %d\n",
power_type);
return power_type;
}
role = cros_ec_usb_get_role(info, &polarity);
if (role < 0) {
if (role != -ENOTCONN) {
dev_err(dev, "failed getting role err = %d\n", role);
return role;
}
} else {
int pd_mux_state;
pd_mux_state = cros_ec_usb_get_pd_mux_state(info);
if (pd_mux_state < 0)
pd_mux_state = USB_PD_MUX_USB_ENABLED;
dp = pd_mux_state & USB_PD_MUX_DP_ENABLED;
mux = pd_mux_state & USB_PD_MUX_USB_ENABLED;
hpd = pd_mux_state & USB_PD_MUX_HPD_IRQ;
}
if (force || info->dp != dp || info->mux != mux ||
info->power_type != power_type) {
info->dp = dp;
info->mux = mux;
info->power_type = power_type;
extcon_set_state(info->edev, EXTCON_DISP_DP, dp);
extcon_set_property(info->edev, EXTCON_DISP_DP,
EXTCON_PROP_USB_TYPEC_POLARITY,
(union extcon_property_value)(int)polarity);
extcon_set_property(info->edev, EXTCON_DISP_DP,
EXTCON_PROP_USB_SS,
(union extcon_property_value)(int)mux);
extcon_set_property(info->edev, EXTCON_DISP_DP,
EXTCON_PROP_DISP_HPD,
(union extcon_property_value)(int)hpd);
extcon_sync(info->edev, EXTCON_DISP_DP);
} else if (hpd) {
extcon_set_property(info->edev, EXTCON_DISP_DP,
EXTCON_PROP_DISP_HPD,
(union extcon_property_value)(int)hpd);
extcon_sync(info->edev, EXTCON_DISP_DP);
}
return 0;
}
static int extcon_cros_ec_event(struct notifier_block *nb,
unsigned long queued_during_suspend,
void *_notify)
{
struct cros_ec_extcon_info *info;
struct cros_ec_device *ec;
u32 host_event;
info = container_of(nb, struct cros_ec_extcon_info, notifier);
ec = info->ec;
host_event = cros_ec_get_host_event(ec);
if (host_event & (EC_HOST_EVENT_MASK(EC_HOST_EVENT_PD_MCU) |
EC_HOST_EVENT_MASK(EC_HOST_EVENT_USB_MUX))) {
extcon_cros_ec_detect_cable(info, false);
return NOTIFY_OK;
}
return NOTIFY_DONE;
}
static int extcon_cros_ec_probe(struct platform_device *pdev)
{
struct cros_ec_extcon_info *info;
struct cros_ec_device *ec = dev_get_drvdata(pdev->dev.parent);
struct device *dev = &pdev->dev;
struct device_node *np = dev->of_node;
int numports, ret;
info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL);
if (!info)
return -ENOMEM;
info->dev = dev;
info->ec = ec;
if (np) {
u32 port;
ret = of_property_read_u32(np, "google,usb-port-id", &port);
if (ret < 0) {
dev_err(dev, "Missing google,usb-port-id property\n");
return ret;
}
info->port_id = port;
} else {
info->port_id = pdev->id;
}
numports = cros_ec_pd_get_num_ports(info);
if (numports < 0) {
dev_err(dev, "failed getting number of ports! ret = %d\n",
numports);
return numports;
}
if (info->port_id >= numports) {
dev_err(dev, "This system only supports %d ports\n", numports);
return -ENODEV;
}
info->edev = devm_extcon_dev_allocate(dev, usb_type_c_cable);
if (IS_ERR(info->edev)) {
dev_err(dev, "failed to allocate extcon device\n");
return -ENOMEM;
}
ret = devm_extcon_dev_register(dev, info->edev);
if (ret < 0) {
dev_err(dev, "failed to register extcon device\n");
return ret;
}
extcon_set_property_capability(info->edev, EXTCON_DISP_DP,
EXTCON_PROP_USB_TYPEC_POLARITY);
extcon_set_property_capability(info->edev, EXTCON_DISP_DP,
EXTCON_PROP_USB_SS);
extcon_set_property_capability(info->edev, EXTCON_DISP_DP,
EXTCON_PROP_DISP_HPD);
platform_set_drvdata(pdev, info);
/* Get PD events from the EC */
info->notifier.notifier_call = extcon_cros_ec_event;
ret = blocking_notifier_chain_register(&info->ec->event_notifier,
&info->notifier);
if (ret < 0) {
dev_err(dev, "failed to register notifier\n");
return ret;
}
/* Perform initial detection */
ret = extcon_cros_ec_detect_cable(info, true);
if (ret < 0) {
dev_err(dev, "failed to detect initial cable state\n");
goto unregister_notifier;
}
return 0;
unregister_notifier:
blocking_notifier_chain_unregister(&info->ec->event_notifier,
&info->notifier);
return ret;
}
static int extcon_cros_ec_remove(struct platform_device *pdev)
{
struct cros_ec_extcon_info *info = platform_get_drvdata(pdev);
blocking_notifier_chain_unregister(&info->ec->event_notifier,
&info->notifier);
return 0;
}
#ifdef CONFIG_PM_SLEEP
static int extcon_cros_ec_suspend(struct device *dev)
{
return 0;
}
static int extcon_cros_ec_resume(struct device *dev)
{
int ret;
struct cros_ec_extcon_info *info = dev_get_drvdata(dev);
ret = extcon_cros_ec_detect_cable(info, true);
if (ret < 0)
dev_err(dev, "failed to detect cable state on resume\n");
return 0;
}
static const struct dev_pm_ops extcon_cros_ec_dev_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(extcon_cros_ec_suspend, extcon_cros_ec_resume)
};
#define DEV_PM_OPS (&extcon_cros_ec_dev_pm_ops)
#else
#define DEV_PM_OPS NULL
#endif /* CONFIG_PM_SLEEP */
#ifdef CONFIG_OF
static const struct of_device_id extcon_cros_ec_of_match[] = {
{ .compatible = "google,extcon-usbc-cros-ec" },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, extcon_cros_ec_of_match);
#endif /* CONFIG_OF */
static struct platform_driver extcon_cros_ec_driver = {
.driver = {
.name = "extcon-usbc-cros-ec",
.of_match_table = of_match_ptr(extcon_cros_ec_of_match),
.pm = DEV_PM_OPS,
},
.remove = extcon_cros_ec_remove,
.probe = extcon_cros_ec_probe,
};
module_platform_driver(extcon_cros_ec_driver);
MODULE_DESCRIPTION("ChromeOS Embedded Controller extcon driver");
MODULE_AUTHOR("Benson Leung <bleung@chromium.org>");
MODULE_LICENSE("GPL");
/* /*
* drivers/extcon/extcon.c - External Connector (extcon) framework. * drivers/extcon/extcon.c - External Connector (extcon) framework.
* *
* External connector (extcon) class driver
*
* Copyright (C) 2015 Samsung Electronics * Copyright (C) 2015 Samsung Electronics
* Author: Chanwoo Choi <cw00.choi@samsung.com> * Author: Chanwoo Choi <cw00.choi@samsung.com>
* *
...@@ -37,7 +35,6 @@ ...@@ -37,7 +35,6 @@
#include "extcon.h" #include "extcon.h"
#define SUPPORTED_CABLE_MAX 32 #define SUPPORTED_CABLE_MAX 32
#define CABLE_NAME_MAX 30
struct __extcon_info { struct __extcon_info {
unsigned int type; unsigned int type;
...@@ -200,13 +197,13 @@ struct __extcon_info { ...@@ -200,13 +197,13 @@ struct __extcon_info {
}; };
/** /**
* struct extcon_cable - An internal data for each cable of extcon device. * struct extcon_cable - An internal data for an external connector.
* @edev: The extcon device * @edev: the extcon device
* @cable_index: Index of this cable in the edev * @cable_index: the index of this cable in the edev
* @attr_g: Attribute group for the cable * @attr_g: the attribute group for the cable
* @attr_name: "name" sysfs entry * @attr_name: "name" sysfs entry
* @attr_state: "state" sysfs entry * @attr_state: "state" sysfs entry
* @attrs: Array pointing to attr_name and attr_state for attr_g * @attrs: the array pointing to attr_name and attr_state for attr_g
*/ */
struct extcon_cable { struct extcon_cable {
struct extcon_dev *edev; struct extcon_dev *edev;
...@@ -234,15 +231,6 @@ static struct class *extcon_class; ...@@ -234,15 +231,6 @@ static struct class *extcon_class;
static LIST_HEAD(extcon_dev_list); static LIST_HEAD(extcon_dev_list);
static DEFINE_MUTEX(extcon_dev_list_lock); static DEFINE_MUTEX(extcon_dev_list_lock);
/**
* check_mutually_exclusive - Check if new_state violates mutually_exclusive
* condition.
* @edev: the extcon device
* @new_state: new cable attach status for @edev
*
* Returns 0 if nothing violates. Returns the index + 1 for the first
* violated condition.
*/
static int check_mutually_exclusive(struct extcon_dev *edev, u32 new_state) static int check_mutually_exclusive(struct extcon_dev *edev, u32 new_state)
{ {
int i = 0; int i = 0;
...@@ -417,11 +405,13 @@ static ssize_t cable_state_show(struct device *dev, ...@@ -417,11 +405,13 @@ static ssize_t cable_state_show(struct device *dev,
} }
/** /**
* extcon_sync() - Synchronize the states for both the attached/detached * extcon_sync() - Synchronize the state for an external connector.
* @edev: the extcon device that has the cable. * @edev: the extcon device
* *
* This function send a notification to synchronize the all states of a * Note that this function send a notification in order to synchronize
* specific external connector * the state and property of an external connector.
*
* Returns 0 if success or error number if fail.
*/ */
int extcon_sync(struct extcon_dev *edev, unsigned int id) int extcon_sync(struct extcon_dev *edev, unsigned int id)
{ {
...@@ -497,9 +487,11 @@ int extcon_sync(struct extcon_dev *edev, unsigned int id) ...@@ -497,9 +487,11 @@ int extcon_sync(struct extcon_dev *edev, unsigned int id)
EXPORT_SYMBOL_GPL(extcon_sync); EXPORT_SYMBOL_GPL(extcon_sync);
/** /**
* extcon_get_state() - Get the state of a external connector. * extcon_get_state() - Get the state of an external connector.
* @edev: the extcon device that has the cable. * @edev: the extcon device
* @id: the unique id of each external connector in extcon enumeration. * @id: the unique id indicating an external connector
*
* Returns 0 if success or error number if fail.
*/ */
int extcon_get_state(struct extcon_dev *edev, const unsigned int id) int extcon_get_state(struct extcon_dev *edev, const unsigned int id)
{ {
...@@ -522,20 +514,19 @@ int extcon_get_state(struct extcon_dev *edev, const unsigned int id) ...@@ -522,20 +514,19 @@ int extcon_get_state(struct extcon_dev *edev, const unsigned int id)
EXPORT_SYMBOL_GPL(extcon_get_state); EXPORT_SYMBOL_GPL(extcon_get_state);
/** /**
* extcon_set_state() - Set the state of a external connector. * extcon_set_state() - Set the state of an external connector.
* without a notification. * @edev: the extcon device
* @edev: the extcon device that has the cable. * @id: the unique id indicating an external connector
* @id: the unique id of each external connector * @state: the new state of an external connector.
* in extcon enumeration. * the default semantics is true: attached / false: detached.
* @state: the new cable status. The default semantics is
* true: attached / false: detached.
* *
* This function only set the state of a external connector without * Note that this function set the state of an external connector without
* a notification. To synchronize the data of a external connector, * a notification. To synchronize the state of an external connector,
* use extcon_set_state_sync() and extcon_sync(). * have to use extcon_set_state_sync() and extcon_sync().
*
* Returns 0 if success or error number if fail.
*/ */
int extcon_set_state(struct extcon_dev *edev, unsigned int id, int extcon_set_state(struct extcon_dev *edev, unsigned int id, bool state)
bool cable_state)
{ {
unsigned long flags; unsigned long flags;
int index, ret = 0; int index, ret = 0;
...@@ -550,11 +541,11 @@ int extcon_set_state(struct extcon_dev *edev, unsigned int id, ...@@ -550,11 +541,11 @@ int extcon_set_state(struct extcon_dev *edev, unsigned int id,
spin_lock_irqsave(&edev->lock, flags); spin_lock_irqsave(&edev->lock, flags);
/* Check whether the external connector's state is changed. */ /* Check whether the external connector's state is changed. */
if (!is_extcon_changed(edev, index, cable_state)) if (!is_extcon_changed(edev, index, state))
goto out; goto out;
if (check_mutually_exclusive(edev, if (check_mutually_exclusive(edev,
(edev->state & ~BIT(index)) | (cable_state & BIT(index)))) { (edev->state & ~BIT(index)) | (state & BIT(index)))) {
ret = -EPERM; ret = -EPERM;
goto out; goto out;
} }
...@@ -563,11 +554,11 @@ int extcon_set_state(struct extcon_dev *edev, unsigned int id, ...@@ -563,11 +554,11 @@ int extcon_set_state(struct extcon_dev *edev, unsigned int id,
* Initialize the value of extcon property before setting * Initialize the value of extcon property before setting
* the detached state for an external connector. * the detached state for an external connector.
*/ */
if (!cable_state) if (!state)
init_property(edev, id, index); init_property(edev, id, index);
/* Update the state for a external connector. */ /* Update the state for an external connector. */
if (cable_state) if (state)
edev->state |= BIT(index); edev->state |= BIT(index);
else else
edev->state &= ~(BIT(index)); edev->state &= ~(BIT(index));
...@@ -579,19 +570,18 @@ int extcon_set_state(struct extcon_dev *edev, unsigned int id, ...@@ -579,19 +570,18 @@ int extcon_set_state(struct extcon_dev *edev, unsigned int id,
EXPORT_SYMBOL_GPL(extcon_set_state); EXPORT_SYMBOL_GPL(extcon_set_state);
/** /**
* extcon_set_state_sync() - Set the state of a external connector * extcon_set_state_sync() - Set the state of an external connector with sync.
* with a notification. * @edev: the extcon device
* @edev: the extcon device that has the cable. * @id: the unique id indicating an external connector
* @id: the unique id of each external connector * @state: the new state of external connector.
* in extcon enumeration. * the default semantics is true: attached / false: detached.
* @state: the new cable status. The default semantics is *
* true: attached / false: detached. * Note that this function set the state of external connector
* and synchronize the state by sending a notification.
* *
* This function set the state of external connector and synchronize the data * Returns 0 if success or error number if fail.
* by usning a notification.
*/ */
int extcon_set_state_sync(struct extcon_dev *edev, unsigned int id, int extcon_set_state_sync(struct extcon_dev *edev, unsigned int id, bool state)
bool cable_state)
{ {
int ret, index; int ret, index;
unsigned long flags; unsigned long flags;
...@@ -602,12 +592,12 @@ int extcon_set_state_sync(struct extcon_dev *edev, unsigned int id, ...@@ -602,12 +592,12 @@ int extcon_set_state_sync(struct extcon_dev *edev, unsigned int id,
/* Check whether the external connector's state is changed. */ /* Check whether the external connector's state is changed. */
spin_lock_irqsave(&edev->lock, flags); spin_lock_irqsave(&edev->lock, flags);
ret = is_extcon_changed(edev, index, cable_state); ret = is_extcon_changed(edev, index, state);
spin_unlock_irqrestore(&edev->lock, flags); spin_unlock_irqrestore(&edev->lock, flags);
if (!ret) if (!ret)
return 0; return 0;
ret = extcon_set_state(edev, id, cable_state); ret = extcon_set_state(edev, id, state);
if (ret < 0) if (ret < 0)
return ret; return ret;
...@@ -616,19 +606,18 @@ int extcon_set_state_sync(struct extcon_dev *edev, unsigned int id, ...@@ -616,19 +606,18 @@ int extcon_set_state_sync(struct extcon_dev *edev, unsigned int id,
EXPORT_SYMBOL_GPL(extcon_set_state_sync); EXPORT_SYMBOL_GPL(extcon_set_state_sync);
/** /**
* extcon_get_property() - Get the property value of a specific cable. * extcon_get_property() - Get the property value of an external connector.
* @edev: the extcon device that has the cable. * @edev: the extcon device
* @id: the unique id of each external connector * @id: the unique id indicating an external connector
* in extcon enumeration. * @prop: the property id indicating an extcon property
* @prop: the property id among enum extcon_property. * @prop_val: the pointer which store the value of extcon property
* @prop_val: the pointer which store the value of property.
* *
* When getting the property value of external connector, the external connector * Note that when getting the property value of external connector,
* should be attached. If detached state, function just return 0 without * the external connector should be attached. If detached state, function
* property value. Also, the each property should be included in the list of * return 0 without property value. Also, the each property should be
* supported properties according to the type of external connectors. * included in the list of supported properties according to extcon type.
* *
* Returns 0 if success or error number if fail * Returns 0 if success or error number if fail.
*/ */
int extcon_get_property(struct extcon_dev *edev, unsigned int id, int extcon_get_property(struct extcon_dev *edev, unsigned int id,
unsigned int prop, unsigned int prop,
...@@ -698,17 +687,16 @@ int extcon_get_property(struct extcon_dev *edev, unsigned int id, ...@@ -698,17 +687,16 @@ int extcon_get_property(struct extcon_dev *edev, unsigned int id,
EXPORT_SYMBOL_GPL(extcon_get_property); EXPORT_SYMBOL_GPL(extcon_get_property);
/** /**
* extcon_set_property() - Set the property value of a specific cable. * extcon_set_property() - Set the property value of an external connector.
* @edev: the extcon device that has the cable. * @edev: the extcon device
* @id: the unique id of each external connector * @id: the unique id indicating an external connector
* in extcon enumeration. * @prop: the property id indicating an extcon property
* @prop: the property id among enum extcon_property. * @prop_val: the pointer including the new value of extcon property
* @prop_val: the pointer including the new value of property.
* *
* The each property should be included in the list of supported properties * Note that each property should be included in the list of supported
* according to the type of external connectors. * properties according to the extcon type.
* *
* Returns 0 if success or error number if fail * Returns 0 if success or error number if fail.
*/ */
int extcon_set_property(struct extcon_dev *edev, unsigned int id, int extcon_set_property(struct extcon_dev *edev, unsigned int id,
unsigned int prop, unsigned int prop,
...@@ -766,15 +754,14 @@ int extcon_set_property(struct extcon_dev *edev, unsigned int id, ...@@ -766,15 +754,14 @@ int extcon_set_property(struct extcon_dev *edev, unsigned int id,
EXPORT_SYMBOL_GPL(extcon_set_property); EXPORT_SYMBOL_GPL(extcon_set_property);
/** /**
* extcon_set_property_sync() - Set the property value of a specific cable * extcon_set_property_sync() - Set property of an external connector with sync.
with a notification. * @prop_val: the pointer including the new value of extcon property
* @prop_val: the pointer including the new value of property.
* *
* When setting the property value of external connector, the external connector * Note that when setting the property value of external connector,
* should be attached. The each property should be included in the list of * the external connector should be attached. The each property should
* supported properties according to the type of external connectors. * be included in the list of supported properties according to extcon type.
* *
* Returns 0 if success or error number if fail * Returns 0 if success or error number if fail.
*/ */
int extcon_set_property_sync(struct extcon_dev *edev, unsigned int id, int extcon_set_property_sync(struct extcon_dev *edev, unsigned int id,
unsigned int prop, unsigned int prop,
...@@ -791,12 +778,11 @@ int extcon_set_property_sync(struct extcon_dev *edev, unsigned int id, ...@@ -791,12 +778,11 @@ int extcon_set_property_sync(struct extcon_dev *edev, unsigned int id,
EXPORT_SYMBOL_GPL(extcon_set_property_sync); EXPORT_SYMBOL_GPL(extcon_set_property_sync);
/** /**
* extcon_get_property_capability() - Get the capability of property * extcon_get_property_capability() - Get the capability of the property
* of an external connector. * for an external connector.
* @edev: the extcon device that has the cable. * @edev: the extcon device
* @id: the unique id of each external connector * @id: the unique id indicating an external connector
* in extcon enumeration. * @prop: the property id indicating an extcon property
* @prop: the property id among enum extcon_property.
* *
* Returns 1 if the property is available or 0 if not available. * Returns 1 if the property is available or 0 if not available.
*/ */
...@@ -822,18 +808,17 @@ int extcon_get_property_capability(struct extcon_dev *edev, unsigned int id, ...@@ -822,18 +808,17 @@ int extcon_get_property_capability(struct extcon_dev *edev, unsigned int id,
EXPORT_SYMBOL_GPL(extcon_get_property_capability); EXPORT_SYMBOL_GPL(extcon_get_property_capability);
/** /**
* extcon_set_property_capability() - Set the capability of a property * extcon_set_property_capability() - Set the capability of the property
* of an external connector. * for an external connector.
* @edev: the extcon device that has the cable. * @edev: the extcon device
* @id: the unique id of each external connector * @id: the unique id indicating an external connector
* in extcon enumeration. * @prop: the property id indicating an extcon property
* @prop: the property id among enum extcon_property.
* *
* This function set the capability of a property for an external connector * Note that this function set the capability of the property
* to mark the bit in capability bitmap which mean the available state of * for an external connector in order to mark the bit in capability
* a property. * bitmap which mean the available state of the property.
* *
* Returns 0 if success or error number if fail * Returns 0 if success or error number if fail.
*/ */
int extcon_set_property_capability(struct extcon_dev *edev, unsigned int id, int extcon_set_property_capability(struct extcon_dev *edev, unsigned int id,
unsigned int prop) unsigned int prop)
...@@ -881,8 +866,10 @@ int extcon_set_property_capability(struct extcon_dev *edev, unsigned int id, ...@@ -881,8 +866,10 @@ int extcon_set_property_capability(struct extcon_dev *edev, unsigned int id,
EXPORT_SYMBOL_GPL(extcon_set_property_capability); EXPORT_SYMBOL_GPL(extcon_set_property_capability);
/** /**
* extcon_get_extcon_dev() - Get the extcon device instance from the name * extcon_get_extcon_dev() - Get the extcon device instance from the name.
* @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.
*/ */
struct extcon_dev *extcon_get_extcon_dev(const char *extcon_name) struct extcon_dev *extcon_get_extcon_dev(const char *extcon_name)
{ {
...@@ -904,15 +891,17 @@ struct extcon_dev *extcon_get_extcon_dev(const char *extcon_name) ...@@ -904,15 +891,17 @@ struct extcon_dev *extcon_get_extcon_dev(const char *extcon_name)
EXPORT_SYMBOL_GPL(extcon_get_extcon_dev); EXPORT_SYMBOL_GPL(extcon_get_extcon_dev);
/** /**
* extcon_register_notifier() - Register a notifiee to get notified by * extcon_register_notifier() - Register a notifier block to get notified by
* any attach status changes from the extcon. * any state changes from the extcon.
* @edev: the extcon device that has the external connecotr. * @edev: the extcon device
* @id: the unique id of each external connector in extcon enumeration. * @id: the unique id indicating an external connector
* @nb: a notifier block to be registered. * @nb: a notifier block to be registered
* *
* Note that the second parameter given to the callback of nb (val) is * Note that the second parameter given to the callback of nb (val) is
* "old_state", not the current state. The current state can be retrieved * the current state of an external connector and the third pameter
* by looking at the third pameter (edev pointer)'s state value. * is the pointer of extcon device.
*
* Returns 0 if success or error number if fail.
*/ */
int extcon_register_notifier(struct extcon_dev *edev, unsigned int id, int extcon_register_notifier(struct extcon_dev *edev, unsigned int id,
struct notifier_block *nb) struct notifier_block *nb)
...@@ -936,10 +925,12 @@ int extcon_register_notifier(struct extcon_dev *edev, unsigned int id, ...@@ -936,10 +925,12 @@ int extcon_register_notifier(struct extcon_dev *edev, unsigned int id,
EXPORT_SYMBOL_GPL(extcon_register_notifier); EXPORT_SYMBOL_GPL(extcon_register_notifier);
/** /**
* extcon_unregister_notifier() - Unregister a notifiee from the extcon device. * extcon_unregister_notifier() - Unregister a notifier block from the extcon.
* @edev: the extcon device that has the external connecotr. * @edev: the extcon device
* @id: the unique id of each external connector in extcon enumeration. * @id: the unique id indicating an external connector
* @nb: a notifier block to be registered. * @nb: a notifier block to be registered
*
* Returns 0 if success or error number if fail.
*/ */
int extcon_unregister_notifier(struct extcon_dev *edev, unsigned int id, int extcon_unregister_notifier(struct extcon_dev *edev, unsigned int id,
struct notifier_block *nb) struct notifier_block *nb)
...@@ -963,16 +954,16 @@ int extcon_unregister_notifier(struct extcon_dev *edev, unsigned int id, ...@@ -963,16 +954,16 @@ int extcon_unregister_notifier(struct extcon_dev *edev, unsigned int id,
EXPORT_SYMBOL_GPL(extcon_unregister_notifier); EXPORT_SYMBOL_GPL(extcon_unregister_notifier);
/** /**
* extcon_register_notifier_all() - Register a notifier block for all connectors * extcon_register_notifier_all() - Register a notifier block for all connectors.
* @edev: the extcon device that has the external connector. * @edev: the extcon device
* @nb: a notifier block to be registered. * @nb: a notifier block to be registered
* *
* This function registers a notifier block in order to receive the state * Note that this function registers a notifier block in order to receive
* change of all supported external connectors from extcon device. * the state change of all supported external connectors from extcon device.
* And the second parameter given to the callback of nb (val) is * And the second parameter given to the callback of nb (val) is
* the current state and third parameter is the edev pointer. * the current state and the third pameter is the pointer of extcon device.
* *
* Returns 0 if success or error number if fail * Returns 0 if success or error number if fail.
*/ */
int extcon_register_notifier_all(struct extcon_dev *edev, int extcon_register_notifier_all(struct extcon_dev *edev,
struct notifier_block *nb) struct notifier_block *nb)
...@@ -993,10 +984,10 @@ EXPORT_SYMBOL_GPL(extcon_register_notifier_all); ...@@ -993,10 +984,10 @@ EXPORT_SYMBOL_GPL(extcon_register_notifier_all);
/** /**
* extcon_unregister_notifier_all() - Unregister a notifier block from extcon. * extcon_unregister_notifier_all() - Unregister a notifier block from extcon.
* @edev: the extcon device that has the external connecotr. * @edev: the extcon device
* @nb: a notifier block to be registered. * @nb: a notifier block to be registered
* *
* Returns 0 if success or error number if fail * Returns 0 if success or error number if fail.
*/ */
int extcon_unregister_notifier_all(struct extcon_dev *edev, int extcon_unregister_notifier_all(struct extcon_dev *edev,
struct notifier_block *nb) struct notifier_block *nb)
...@@ -1045,15 +1036,14 @@ static void dummy_sysfs_dev_release(struct device *dev) ...@@ -1045,15 +1036,14 @@ static void dummy_sysfs_dev_release(struct device *dev)
/* /*
* extcon_dev_allocate() - Allocate the memory of extcon device. * extcon_dev_allocate() - Allocate the memory of extcon device.
* @supported_cable: Array of supported extcon ending with EXTCON_NONE. * @supported_cable: the array of the supported external connectors
* If supported_cable is NULL, cable name related APIs * ending with EXTCON_NONE.
* are disabled.
* *
* This function allocates the memory for extcon device without allocating * Note that this function allocates the memory for extcon device
* memory in each extcon provider driver and initialize default setting for * and initialize default setting for the extcon device.
* extcon device.
* *
* Return the pointer of extcon device if success or ERR_PTR(err) if fail * Returns the pointer memory of allocated extcon_dev if success
* or ERR_PTR(err) if fail.
*/ */
struct extcon_dev *extcon_dev_allocate(const unsigned int *supported_cable) struct extcon_dev *extcon_dev_allocate(const unsigned int *supported_cable)
{ {
...@@ -1074,7 +1064,7 @@ struct extcon_dev *extcon_dev_allocate(const unsigned int *supported_cable) ...@@ -1074,7 +1064,7 @@ struct extcon_dev *extcon_dev_allocate(const unsigned int *supported_cable)
/* /*
* extcon_dev_free() - Free the memory of extcon device. * extcon_dev_free() - Free the memory of extcon device.
* @edev: the extcon device to free * @edev: the extcon device
*/ */
void extcon_dev_free(struct extcon_dev *edev) void extcon_dev_free(struct extcon_dev *edev)
{ {
...@@ -1083,13 +1073,18 @@ void extcon_dev_free(struct extcon_dev *edev) ...@@ -1083,13 +1073,18 @@ void extcon_dev_free(struct extcon_dev *edev)
EXPORT_SYMBOL_GPL(extcon_dev_free); EXPORT_SYMBOL_GPL(extcon_dev_free);
/** /**
* extcon_dev_register() - Register a new extcon device * extcon_dev_register() - Register an new extcon device
* @edev : the new extcon device (should be allocated before calling) * @edev: the extcon device to be registered
* *
* Among the members of edev struct, please set the "user initializing data" * Among the members of edev struct, please set the "user initializing data"
* in any case and set the "optional callbacks" if required. However, please
* do not set the values of "internal data", which are initialized by * do not set the values of "internal data", which are initialized by
* this function. * this function.
*
* Note that before calling this funciton, have to allocate the memory
* of an extcon device by using the extcon_dev_allocate(). And the extcon
* dev should include the supported_cable information.
*
* Returns 0 if success or error number if fail.
*/ */
int extcon_dev_register(struct extcon_dev *edev) int extcon_dev_register(struct extcon_dev *edev)
{ {
...@@ -1296,7 +1291,7 @@ EXPORT_SYMBOL_GPL(extcon_dev_register); ...@@ -1296,7 +1291,7 @@ EXPORT_SYMBOL_GPL(extcon_dev_register);
/** /**
* extcon_dev_unregister() - Unregister the extcon device. * extcon_dev_unregister() - Unregister the extcon device.
* @edev: the extcon device instance to be unregistered. * @edev: the extcon device to be unregistered.
* *
* Note that this does not call kfree(edev) because edev was not allocated * Note that this does not call kfree(edev) because edev was not allocated
* by this class. * by this class.
...@@ -1342,11 +1337,11 @@ EXPORT_SYMBOL_GPL(extcon_dev_unregister); ...@@ -1342,11 +1337,11 @@ EXPORT_SYMBOL_GPL(extcon_dev_unregister);
#ifdef CONFIG_OF #ifdef CONFIG_OF
/* /*
* extcon_get_edev_by_phandle - Get the extcon device from devicetree * extcon_get_edev_by_phandle - Get the extcon device from devicetree.
* @dev - instance to the given device * @dev : the instance to the given device
* @index - index into list of extcon_dev * @index : the index into list of extcon_dev
* *
* return the instance of extcon device * Return the pointer of extcon device if success or ERR_PTR(err) if fail.
*/ */
struct extcon_dev *extcon_get_edev_by_phandle(struct device *dev, int index) struct extcon_dev *extcon_get_edev_by_phandle(struct device *dev, int index)
{ {
...@@ -1363,8 +1358,8 @@ struct extcon_dev *extcon_get_edev_by_phandle(struct device *dev, int index) ...@@ -1363,8 +1358,8 @@ struct extcon_dev *extcon_get_edev_by_phandle(struct device *dev, int index)
node = of_parse_phandle(dev->of_node, "extcon", index); node = of_parse_phandle(dev->of_node, "extcon", index);
if (!node) { if (!node) {
dev_dbg(dev, "failed to get phandle in %s node\n", dev_dbg(dev, "failed to get phandle in %pOF node\n",
dev->of_node->full_name); dev->of_node);
return ERR_PTR(-ENODEV); return ERR_PTR(-ENODEV);
} }
...@@ -1411,8 +1406,6 @@ static void __exit extcon_class_exit(void) ...@@ -1411,8 +1406,6 @@ static void __exit extcon_class_exit(void)
module_exit(extcon_class_exit); module_exit(extcon_class_exit);
MODULE_AUTHOR("Chanwoo Choi <cw00.choi@samsung.com>"); MODULE_AUTHOR("Chanwoo Choi <cw00.choi@samsung.com>");
MODULE_AUTHOR("Mike Lockwood <lockwood@android.com>");
MODULE_AUTHOR("Donggeun Kim <dg77.kim@samsung.com>");
MODULE_AUTHOR("MyungJoo Ham <myungjoo.ham@samsung.com>"); MODULE_AUTHOR("MyungJoo Ham <myungjoo.ham@samsung.com>");
MODULE_DESCRIPTION("External connector (extcon) class driver"); MODULE_DESCRIPTION("External Connector (extcon) framework");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL v2");
...@@ -253,16 +253,16 @@ static void extcon_work(struct work_struct *work) ...@@ -253,16 +253,16 @@ static void extcon_work(struct work_struct *work)
vbus = gpiod_get_value_cansleep(driver->vbus_gpiod); vbus = gpiod_get_value_cansleep(driver->vbus_gpiod);
if (!id && vbus) { /* Host connected */ if (!id && vbus) { /* Host connected */
extcon_set_cable_state_(driver->edev, EXTCON_USB_HOST, true); extcon_set_state_sync(driver->edev, EXTCON_USB_HOST, true);
pr_debug("Host cable connected\n"); pr_debug("Host cable connected\n");
driver->data->new_state = EVT_HOST; driver->data->new_state = EVT_HOST;
connect_change(driver); connect_change(driver);
} else if (id && !vbus) { /* Disconnected */ } else if (id && !vbus) { /* Disconnected */
extcon_set_cable_state_(driver->edev, EXTCON_USB_HOST, false); extcon_set_state_sync(driver->edev, EXTCON_USB_HOST, false);
extcon_set_cable_state_(driver->edev, EXTCON_USB, false); extcon_set_state_sync(driver->edev, EXTCON_USB, false);
pr_debug("Cable disconnected\n"); pr_debug("Cable disconnected\n");
} else if (id && vbus) { /* Device connected */ } else if (id && vbus) { /* Device connected */
extcon_set_cable_state_(driver->edev, EXTCON_USB, true); extcon_set_state_sync(driver->edev, EXTCON_USB, true);
pr_debug("Device cable connected\n"); pr_debug("Device cable connected\n");
driver->data->new_state = EVT_DEVICE; driver->data->new_state = EVT_DEVICE;
connect_change(driver); connect_change(driver);
......
...@@ -155,12 +155,12 @@ static int qcom_usb_hs_phy_power_on(struct phy *phy) ...@@ -155,12 +155,12 @@ static int qcom_usb_hs_phy_power_on(struct phy *phy)
} }
if (uphy->vbus_edev) { if (uphy->vbus_edev) {
state = extcon_get_cable_state_(uphy->vbus_edev, EXTCON_USB); state = extcon_get_state(uphy->vbus_edev, EXTCON_USB);
/* setup initial state */ /* setup initial state */
qcom_usb_hs_phy_vbus_notifier(&uphy->vbus_notify, state, qcom_usb_hs_phy_vbus_notifier(&uphy->vbus_notify, state,
uphy->vbus_edev); uphy->vbus_edev);
ret = extcon_register_notifier(uphy->vbus_edev, EXTCON_USB, ret = devm_extcon_register_notifier(&ulpi->dev, uphy->vbus_edev,
&uphy->vbus_notify); EXTCON_USB, &uphy->vbus_notify);
if (ret) if (ret)
goto err_ulpi; goto err_ulpi;
} }
...@@ -179,16 +179,8 @@ static int qcom_usb_hs_phy_power_on(struct phy *phy) ...@@ -179,16 +179,8 @@ static int qcom_usb_hs_phy_power_on(struct phy *phy)
static int qcom_usb_hs_phy_power_off(struct phy *phy) static int qcom_usb_hs_phy_power_off(struct phy *phy)
{ {
int ret;
struct qcom_usb_hs_phy *uphy = phy_get_drvdata(phy); struct qcom_usb_hs_phy *uphy = phy_get_drvdata(phy);
if (uphy->vbus_edev) {
ret = extcon_unregister_notifier(uphy->vbus_edev, EXTCON_USB,
&uphy->vbus_notify);
if (ret)
return ret;
}
regulator_disable(uphy->v3p3); regulator_disable(uphy->v3p3);
regulator_disable(uphy->v1p8); regulator_disable(uphy->v1p8);
clk_disable_unprepare(uphy->sleep_clk); clk_disable_unprepare(uphy->sleep_clk);
......
...@@ -545,7 +545,7 @@ static void rockchip_usb2phy_otg_sm_work(struct work_struct *work) ...@@ -545,7 +545,7 @@ static void rockchip_usb2phy_otg_sm_work(struct work_struct *work)
rockchip_usb2phy_power_off(rport->phy); rockchip_usb2phy_power_off(rport->phy);
/* fall through */ /* fall through */
case OTG_STATE_B_IDLE: case OTG_STATE_B_IDLE:
if (extcon_get_cable_state_(rphy->edev, EXTCON_USB_HOST) > 0) { if (extcon_get_state(rphy->edev, EXTCON_USB_HOST) > 0) {
dev_dbg(&rport->phy->dev, "usb otg host connect\n"); dev_dbg(&rport->phy->dev, "usb otg host connect\n");
rport->state = OTG_STATE_A_HOST; rport->state = OTG_STATE_A_HOST;
rockchip_usb2phy_power_on(rport->phy); rockchip_usb2phy_power_on(rport->phy);
...@@ -598,7 +598,7 @@ static void rockchip_usb2phy_otg_sm_work(struct work_struct *work) ...@@ -598,7 +598,7 @@ static void rockchip_usb2phy_otg_sm_work(struct work_struct *work)
rport->vbus_attached = vbus_attach; rport->vbus_attached = vbus_attach;
if (notify_charger && rphy->edev) { if (notify_charger && rphy->edev) {
extcon_set_cable_state_(rphy->edev, extcon_set_state_sync(rphy->edev,
cable, vbus_attach); cable, vbus_attach);
if (cable == EXTCON_CHG_USB_SDP) if (cable == EXTCON_CHG_USB_SDP)
extcon_set_state_sync(rphy->edev, extcon_set_state_sync(rphy->edev,
...@@ -619,7 +619,7 @@ static void rockchip_usb2phy_otg_sm_work(struct work_struct *work) ...@@ -619,7 +619,7 @@ static void rockchip_usb2phy_otg_sm_work(struct work_struct *work)
sch_work = true; sch_work = true;
break; break;
case OTG_STATE_A_HOST: case OTG_STATE_A_HOST:
if (extcon_get_cable_state_(rphy->edev, EXTCON_USB_HOST) == 0) { if (extcon_get_state(rphy->edev, EXTCON_USB_HOST) == 0) {
dev_dbg(&rport->phy->dev, "usb otg host disconnect\n"); dev_dbg(&rport->phy->dev, "usb otg host disconnect\n");
rport->state = OTG_STATE_B_IDLE; rport->state = OTG_STATE_B_IDLE;
rockchip_usb2phy_power_off(rport->phy); rockchip_usb2phy_power_off(rport->phy);
...@@ -1006,8 +1006,8 @@ static int rockchip_usb2phy_otg_port_init(struct rockchip_usb2phy *rphy, ...@@ -1006,8 +1006,8 @@ static int rockchip_usb2phy_otg_port_init(struct rockchip_usb2phy *rphy,
if (!IS_ERR(rphy->edev)) { if (!IS_ERR(rphy->edev)) {
rport->event_nb.notifier_call = rockchip_otg_event; rport->event_nb.notifier_call = rockchip_otg_event;
ret = extcon_register_notifier(rphy->edev, EXTCON_USB_HOST, ret = devm_extcon_register_notifier(rphy->dev, rphy->edev,
&rport->event_nb); EXTCON_USB_HOST, &rport->event_nb);
if (ret) if (ret)
dev_err(rphy->dev, "register USB HOST notifier failed\n"); dev_err(rphy->dev, "register USB HOST notifier failed\n");
} }
......
...@@ -184,7 +184,7 @@ static int udc_plat_probe(struct platform_device *pdev) ...@@ -184,7 +184,7 @@ static int udc_plat_probe(struct platform_device *pdev)
goto exit_phy; goto exit_phy;
} }
ret = extcon_get_cable_state_(udc->edev, EXTCON_USB); ret = extcon_get_state(udc->edev, EXTCON_USB);
if (ret < 0) { if (ret < 0) {
dev_err(dev, "Can't get cable state\n"); dev_err(dev, "Can't get cable state\n");
goto exit_extcon; goto exit_extcon;
...@@ -273,7 +273,7 @@ static int udc_plat_suspend(struct device *dev) ...@@ -273,7 +273,7 @@ static int udc_plat_suspend(struct device *dev)
udc = dev_get_drvdata(dev); udc = dev_get_drvdata(dev);
stop_udc(udc); stop_udc(udc);
if (extcon_get_cable_state_(udc->edev, EXTCON_USB) > 0) { if (extcon_get_state(udc->edev, EXTCON_USB) > 0) {
dev_dbg(udc->dev, "device -> idle\n"); dev_dbg(udc->dev, "device -> idle\n");
stop_udc(udc); stop_udc(udc);
} }
...@@ -303,7 +303,7 @@ static int udc_plat_resume(struct device *dev) ...@@ -303,7 +303,7 @@ static int udc_plat_resume(struct device *dev)
return ret; return ret;
} }
if (extcon_get_cable_state_(udc->edev, EXTCON_USB) > 0) { if (extcon_get_state(udc->edev, EXTCON_USB) > 0) {
dev_dbg(udc->dev, "idle -> device\n"); dev_dbg(udc->dev, "idle -> device\n");
start_udc(udc); start_udc(udc);
} }
......
/* /*
* External connector (extcon) class driver * External Connector (extcon) framework
* *
* Copyright (C) 2015 Samsung Electronics * Copyright (C) 2015 Samsung Electronics
* Author: Chanwoo Choi <cw00.choi@samsung.com> * Author: Chanwoo Choi <cw00.choi@samsung.com>
...@@ -20,8 +20,7 @@ ...@@ -20,8 +20,7 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* */
*/
#ifndef __LINUX_EXTCON_H__ #ifndef __LINUX_EXTCON_H__
#define __LINUX_EXTCON_H__ #define __LINUX_EXTCON_H__
...@@ -93,7 +92,7 @@ ...@@ -93,7 +92,7 @@
#define EXTCON_NUM 63 #define EXTCON_NUM 63
/* /*
* Define the property of supported external connectors. * Define the properties of supported external connectors.
* *
* When adding the new extcon property, they *must* have * When adding the new extcon property, they *must* have
* the type/value/default information. Also, you *have to* * the type/value/default information. Also, you *have to*
...@@ -176,44 +175,42 @@ struct extcon_dev; ...@@ -176,44 +175,42 @@ struct extcon_dev;
#if IS_ENABLED(CONFIG_EXTCON) #if IS_ENABLED(CONFIG_EXTCON)
/* /* Following APIs register/unregister the extcon device. */
* Following APIs are for notifiers or configurations.
* Notifiers are the external port and connection devices.
*/
extern int extcon_dev_register(struct extcon_dev *edev); extern int extcon_dev_register(struct extcon_dev *edev);
extern void extcon_dev_unregister(struct extcon_dev *edev); extern void extcon_dev_unregister(struct extcon_dev *edev);
extern int devm_extcon_dev_register(struct device *dev, extern int devm_extcon_dev_register(struct device *dev,
struct extcon_dev *edev); struct extcon_dev *edev);
extern void devm_extcon_dev_unregister(struct device *dev, extern void devm_extcon_dev_unregister(struct device *dev,
struct extcon_dev *edev); struct extcon_dev *edev);
extern struct extcon_dev *extcon_get_extcon_dev(const char *extcon_name);
/* /* Following APIs allocate/free the memory of the extcon device. */
* Following APIs control the memory of extcon device.
*/
extern struct extcon_dev *extcon_dev_allocate(const unsigned int *cable); extern struct extcon_dev *extcon_dev_allocate(const unsigned int *cable);
extern void extcon_dev_free(struct extcon_dev *edev); extern void extcon_dev_free(struct extcon_dev *edev);
extern struct extcon_dev *devm_extcon_dev_allocate(struct device *dev, extern struct extcon_dev *devm_extcon_dev_allocate(struct device *dev,
const unsigned int *cable); const unsigned int *cable);
extern void devm_extcon_dev_free(struct device *dev, struct extcon_dev *edev); extern void devm_extcon_dev_free(struct device *dev, struct extcon_dev *edev);
/* Synchronize the state and property value for each external connector. */
extern int extcon_sync(struct extcon_dev *edev, unsigned int id);
/* /*
* get/set_state access each bit of the 32b encoded state value. * Following APIs get/set the connected state of each external connector.
* They are used to access the status of each cable based on the cable id. * The 'id' argument indicates the defined external connector.
*/ */
extern int extcon_get_state(struct extcon_dev *edev, unsigned int id); extern int extcon_get_state(struct extcon_dev *edev, unsigned int id);
extern int extcon_set_state(struct extcon_dev *edev, unsigned int id, extern int extcon_set_state(struct extcon_dev *edev, unsigned int id,
bool cable_state); bool state);
extern int extcon_set_state_sync(struct extcon_dev *edev, unsigned int id, extern int extcon_set_state_sync(struct extcon_dev *edev, unsigned int id,
bool cable_state); bool state);
/*
* Synchronize the state and property data for a specific external connector.
*/
extern int extcon_sync(struct extcon_dev *edev, unsigned int id);
/* /*
* get/set_property access the property value of each external connector. * Following APIs get/set the property of each external connector.
* They are used to access the property of each cable based on the property id. * The 'id' argument indicates the defined external connector
* and the 'prop' indicates the extcon property.
*
* And extcon_get/set_property_capability() set the capability of the property
* for each external connector. They are used to set the capability of the
* property of each external connector based on the id and property.
*/ */
extern int extcon_get_property(struct extcon_dev *edev, unsigned int id, extern int extcon_get_property(struct extcon_dev *edev, unsigned int id,
unsigned int prop, unsigned int prop,
...@@ -224,19 +221,15 @@ extern int extcon_set_property(struct extcon_dev *edev, unsigned int id, ...@@ -224,19 +221,15 @@ extern int extcon_set_property(struct extcon_dev *edev, unsigned int id,
extern int extcon_set_property_sync(struct extcon_dev *edev, unsigned int id, extern int extcon_set_property_sync(struct extcon_dev *edev, unsigned int id,
unsigned int prop, unsigned int prop,
union extcon_property_value prop_val); union extcon_property_value prop_val);
/*
* get/set_property_capability set the capability of the property for each
* external connector. They are used to set the capability of the property
* of each external connector based on the id and property.
*/
extern int extcon_get_property_capability(struct extcon_dev *edev, extern int extcon_get_property_capability(struct extcon_dev *edev,
unsigned int id, unsigned int prop); unsigned int id, unsigned int prop);
extern int extcon_set_property_capability(struct extcon_dev *edev, extern int extcon_set_property_capability(struct extcon_dev *edev,
unsigned int id, unsigned int prop); unsigned int id, unsigned int prop);
/* /*
* Following APIs are to monitor the status change of the external connectors. * Following APIs register the notifier block in order to detect
* the change of both state and property value for each external connector.
*
* extcon_register_notifier(*edev, id, *nb) : Register a notifier block * extcon_register_notifier(*edev, id, *nb) : Register a notifier block
* for specific external connector of the extcon. * for specific external connector of the extcon.
* extcon_register_notifier_all(*edev, *nb) : Register a notifier block * extcon_register_notifier_all(*edev, *nb) : Register a notifier block
...@@ -265,16 +258,15 @@ extern void devm_extcon_unregister_notifier_all(struct device *dev, ...@@ -265,16 +258,15 @@ extern void devm_extcon_unregister_notifier_all(struct device *dev,
struct notifier_block *nb); struct notifier_block *nb);
/* /*
* Following API get the extcon device from devicetree. * Following APIs get the extcon_dev from devicetree or by through extcon name.
* This function use phandle of devicetree to get extcon device directly.
*/ */
extern struct extcon_dev *extcon_get_extcon_dev(const char *extcon_name);
extern struct extcon_dev *extcon_get_edev_by_phandle(struct device *dev, extern struct extcon_dev *extcon_get_edev_by_phandle(struct device *dev,
int index); int index);
/* Following API to get information of extcon device */ /* Following API get the name of extcon device. */
extern const char *extcon_get_edev_name(struct extcon_dev *edev); extern const char *extcon_get_edev_name(struct extcon_dev *edev);
#else /* CONFIG_EXTCON */ #else /* CONFIG_EXTCON */
static inline int extcon_dev_register(struct extcon_dev *edev) static inline int extcon_dev_register(struct extcon_dev *edev)
{ {
...@@ -314,13 +306,13 @@ static inline int extcon_get_state(struct extcon_dev *edev, unsigned int id) ...@@ -314,13 +306,13 @@ static inline int extcon_get_state(struct extcon_dev *edev, unsigned int id)
} }
static inline int extcon_set_state(struct extcon_dev *edev, unsigned int id, static inline int extcon_set_state(struct extcon_dev *edev, unsigned int id,
bool cable_state) bool state)
{ {
return 0; return 0;
} }
static inline int extcon_set_state_sync(struct extcon_dev *edev, unsigned int id, static inline int extcon_set_state_sync(struct extcon_dev *edev, unsigned int id,
bool cable_state) bool state)
{ {
return 0; return 0;
} }
...@@ -362,21 +354,14 @@ static inline int extcon_set_property_capability(struct extcon_dev *edev, ...@@ -362,21 +354,14 @@ static inline int extcon_set_property_capability(struct extcon_dev *edev,
return 0; return 0;
} }
static inline struct extcon_dev *extcon_get_extcon_dev(const char *extcon_name)
{
return NULL;
}
static inline int extcon_register_notifier(struct extcon_dev *edev, static inline int extcon_register_notifier(struct extcon_dev *edev,
unsigned int id, unsigned int id, struct notifier_block *nb)
struct notifier_block *nb)
{ {
return 0; return 0;
} }
static inline int extcon_unregister_notifier(struct extcon_dev *edev, static inline int extcon_unregister_notifier(struct extcon_dev *edev,
unsigned int id, unsigned int id, struct notifier_block *nb)
struct notifier_block *nb)
{ {
return 0; return 0;
} }
...@@ -392,6 +377,11 @@ static inline void devm_extcon_unregister_notifier(struct device *dev, ...@@ -392,6 +377,11 @@ static inline void devm_extcon_unregister_notifier(struct device *dev,
struct extcon_dev *edev, unsigned int id, struct extcon_dev *edev, unsigned int id,
struct notifier_block *nb) { } struct notifier_block *nb) { }
static inline struct extcon_dev *extcon_get_extcon_dev(const char *extcon_name)
{
return ERR_PTR(-ENODEV);
}
static inline struct extcon_dev *extcon_get_edev_by_phandle(struct device *dev, static inline struct extcon_dev *extcon_get_edev_by_phandle(struct device *dev,
int index) int index)
{ {
...@@ -417,20 +407,8 @@ static inline int extcon_register_interest(struct extcon_specific_cable_nb *obj, ...@@ -417,20 +407,8 @@ static inline int extcon_register_interest(struct extcon_specific_cable_nb *obj,
return -EINVAL; return -EINVAL;
} }
static inline int extcon_unregister_interest(struct extcon_specific_cable_nb static inline int extcon_unregister_interest(struct extcon_specific_cable_nb *obj)
*obj)
{ {
return -EINVAL; return -EINVAL;
} }
static inline int extcon_get_cable_state_(struct extcon_dev *edev, unsigned int id)
{
return extcon_get_state(edev, id);
}
static inline int extcon_set_cable_state_(struct extcon_dev *edev, unsigned int id,
bool cable_state)
{
return extcon_set_state_sync(edev, id, cable_state);
}
#endif /* __LINUX_EXTCON_H__ */ #endif /* __LINUX_EXTCON_H__ */
...@@ -285,6 +285,11 @@ enum host_event_code { ...@@ -285,6 +285,11 @@ enum host_event_code {
EC_HOST_EVENT_HANG_DETECT = 20, EC_HOST_EVENT_HANG_DETECT = 20,
/* Hang detect logic detected a hang and warm rebooted the AP */ /* Hang detect logic detected a hang and warm rebooted the AP */
EC_HOST_EVENT_HANG_REBOOT = 21, EC_HOST_EVENT_HANG_REBOOT = 21,
/* PD MCU triggering host event */
EC_HOST_EVENT_PD_MCU = 22,
/* EC desires to change state of host-controlled USB mux */
EC_HOST_EVENT_USB_MUX = 28,
/* /*
* The high bit of the event mask is not used as a host event code. If * The high bit of the event mask is not used as a host event code. If
...@@ -2905,6 +2910,76 @@ struct ec_params_usb_pd_control { ...@@ -2905,6 +2910,76 @@ struct ec_params_usb_pd_control {
uint8_t mux; uint8_t mux;
} __packed; } __packed;
#define PD_CTRL_RESP_ENABLED_COMMS (1 << 0) /* Communication enabled */
#define PD_CTRL_RESP_ENABLED_CONNECTED (1 << 1) /* Device connected */
#define PD_CTRL_RESP_ENABLED_PD_CAPABLE (1 << 2) /* Partner is PD capable */
struct ec_response_usb_pd_control_v1 {
uint8_t enabled;
uint8_t role;
uint8_t polarity;
char state[32];
} __packed;
#define EC_CMD_USB_PD_PORTS 0x102
struct ec_response_usb_pd_ports {
uint8_t num_ports;
} __packed;
#define EC_CMD_USB_PD_POWER_INFO 0x103
#define PD_POWER_CHARGING_PORT 0xff
struct ec_params_usb_pd_power_info {
uint8_t port;
} __packed;
enum usb_chg_type {
USB_CHG_TYPE_NONE,
USB_CHG_TYPE_PD,
USB_CHG_TYPE_C,
USB_CHG_TYPE_PROPRIETARY,
USB_CHG_TYPE_BC12_DCP,
USB_CHG_TYPE_BC12_CDP,
USB_CHG_TYPE_BC12_SDP,
USB_CHG_TYPE_OTHER,
USB_CHG_TYPE_VBUS,
USB_CHG_TYPE_UNKNOWN,
};
struct usb_chg_measures {
uint16_t voltage_max;
uint16_t voltage_now;
uint16_t current_max;
uint16_t current_lim;
} __packed;
struct ec_response_usb_pd_power_info {
uint8_t role;
uint8_t type;
uint8_t dualrole;
uint8_t reserved1;
struct usb_chg_measures meas;
uint32_t max_power;
} __packed;
/* Get info about USB-C SS muxes */
#define EC_CMD_USB_PD_MUX_INFO 0x11a
struct ec_params_usb_pd_mux_info {
uint8_t port; /* USB-C port number */
} __packed;
/* Flags representing mux state */
#define USB_PD_MUX_USB_ENABLED (1 << 0)
#define USB_PD_MUX_DP_ENABLED (1 << 1)
#define USB_PD_MUX_POLARITY_INVERTED (1 << 2)
#define USB_PD_MUX_HPD_IRQ (1 << 3)
struct ec_response_usb_pd_mux_info {
uint8_t flags; /* USB_PD_MUX_*-encoded USB mux state */
} __packed;
/*****************************************************************************/ /*****************************************************************************/
/* /*
* Passthru commands * Passthru commands
......
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