mirror of
https://github.com/torvalds/linux.git
synced 2026-05-31 18:43:33 +02:00
Update extcon next for v6.5
Detailed description for this pull request: 1. Clean-up extcon core without any behavior changes - Add extcon_alloc_cables/muex/groups to improve the readability of extcon_dev_register. - Fix kernel doc of property and property capability fields to aovid warnings and add missing description of struct extcon_dev. - Use DECLARE_BITMAP macro and sysfs_emit instead of sprintf - Use device_match_of_node helper instead of accessing the .of_node - Use ida_alloc/free to get the unique id for extcon device 2. Update extcon-usbc-tusb320.c to support usb_role_switch and accessory detection - Add usb_role_switch support on extcon-usbsc-tusb320. - Add additional accessory detection for audio/debug accessory and then pass the deteced accessory information to typec subsystem on extcon-usbsc-tusb320.c. - Add the support of unregistration of typec port on both error handling and driver removal step on 3. Update extcon provider drivers (apx288/qcom-spmi-misc/palmas) - Replace put_device with acpi_dev_put on extcon-axp288.c - Use platform_get_irq_byname_optional for getting irq of usb_id and usb_vbus on extcon-qcom-spmi-misc.c. - Remove unused of_gpio.h on extcon-palmas.c. 4. Fix the devicetree binding document - Rename misc node name to 'usb-dect@900' on pm8941-misc.yam - Fix usb-id and usb_vbus defintion on pm8941-misc.yaml - Drop unneeded quotes from extcon-arizona.c devicetree documentation -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEsSpuqBtbWtRe4rLGnM3fLN7rz1MFAmSQYzMACgkQnM3fLN7r z1MEmQ/+PQYDL5XBYEAunp1jURWHFVC+ee9DMq0L9gx2OSZ32nNslCAXrtElGQYF FG/bh+frPVRUSrYklDUBT1aQ87acE3aGIElfwf+GTjUksvi/tTwY/JaA58Y5IthF ZF86WBd1vDhTtMs0MCzfTZimfGWpckuBUEYr9yj0HJNc9ECh6tIdrJfReUF9SOtV wZ6HGC/13jr31cGiMW11sH5kImz7y4AAe7Q1ZYlEGaut1mfmcDxLjeW9GqQLxqme bHFThcXP+NESuB+7kLEEGtoCp3Tyyt5Je15onmVine7Vznwr0blUVv+d1NtdWNPX 85mtqCSASiRSqXaUccqabjs2fKXP7gOFE+3t0cMaBRMfn3+Zd6mscBEMVOFXskA3 WbvhFSX5UiY1pgGRW6sDMujrpItgS9KioJuFxOf3uRgZNy7tyJYQRaEp+5Dh7bBN LksNfE5vXdMJKgMw/g/b7WalPj8REsiiYGCignCCEs1MB2gjUryrqT0WzLu/LKSC OpH+xd08D7H7xu4jqWiD0ZkQs7OTACpj5GT1Xg7CsLwOhlthzHSs+sypi9h8+wVw tToQXqSyfjrLgk0O6Ry+vKfzfgQoZqM4m4JjF8Pce1NctU3MWwhBU6hwRjeEj3lv f5BppEk2VYDr6ofy1+OucrF/njR6QrTDlWdU8G+1g8PStWNrl4U= =3D98 -----END PGP SIGNATURE----- Merge tag 'extcon-next-for-6.5' of git://git.kernel.org/pub/scm/linux/kernel/git/chanwoo/extcon into char-misc-next Chanwoo writes: Update extcon next for v6.5 Detailed description for this pull request: 1. Clean-up extcon core without any behavior changes - Add extcon_alloc_cables/muex/groups to improve the readability of extcon_dev_register. - Fix kernel doc of property and property capability fields to aovid warnings and add missing description of struct extcon_dev. - Use DECLARE_BITMAP macro and sysfs_emit instead of sprintf - Use device_match_of_node helper instead of accessing the .of_node - Use ida_alloc/free to get the unique id for extcon device 2. Update extcon-usbc-tusb320.c to support usb_role_switch and accessory detection - Add usb_role_switch support on extcon-usbsc-tusb320. - Add additional accessory detection for audio/debug accessory and then pass the deteced accessory information to typec subsystem on extcon-usbsc-tusb320.c. - Add the support of unregistration of typec port on both error handling and driver removal step on 3. Update extcon provider drivers (apx288/qcom-spmi-misc/palmas) - Replace put_device with acpi_dev_put on extcon-axp288.c - Use platform_get_irq_byname_optional for getting irq of usb_id and usb_vbus on extcon-qcom-spmi-misc.c. - Remove unused of_gpio.h on extcon-palmas.c. 4. Fix the devicetree binding document - Rename misc node name to 'usb-dect@900' on pm8941-misc.yam - Fix usb-id and usb_vbus defintion on pm8941-misc.yaml - Drop unneeded quotes from extcon-arizona.c devicetree documentation * tag 'extcon-next-for-6.5' of git://git.kernel.org/pub/scm/linux/kernel/git/chanwoo/extcon: (26 commits) dt-bindings: extcon: wlf,arizona: drop unneeded quotes extcon: Switch i2c drivers back to use .probe() extcon: Drop unneeded assignments extcon: Use sizeof(*pointer) instead of sizeof(type) extcon: Use unique number for the extcon device ID extcon: Remove dup device name in the message and unneeded error check extcon: Use dev_of_node(dev) instead of dev->of_node extcon: Use device_match_of_node() helper extcon: Amend kernel documentation of struct extcon_dev extcon: Use sysfs_emit() to instead of sprintf() extcon: Use DECLARE_BITMAP() to declare bit arrays extcon: Fix kernel doc of property capability fields to avoid warnings extcon: Fix kernel doc of property fields to avoid warnings extcon: usbc-tusb320: add USB_ROLE_SWITCH dependency extcon: usbc-tusb320: add usb_role_switch support extcon: usbc-tusb320: add accessory detection support extcon: Add extcon_alloc_groups to simplify extcon register function extcon: Add extcon_alloc_muex to simplify extcon register function extcon: Add extcon_alloc_cables to simplify extcon register function extcon: Remove redundant null checking for class ...
This commit is contained in:
commit
afc5fddd39
|
|
@ -27,10 +27,14 @@ properties:
|
|||
|
||||
interrupt-names:
|
||||
minItems: 1
|
||||
items:
|
||||
- const: usb_id
|
||||
- const: usb_vbus
|
||||
|
||||
anyOf:
|
||||
- items:
|
||||
- const: usb_id
|
||||
- const: usb_vbus
|
||||
- items:
|
||||
- const: usb_id
|
||||
- items:
|
||||
- const: usb_vbus
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
|
@ -49,7 +53,7 @@ examples:
|
|||
interrupt-controller;
|
||||
#interrupt-cells = <4>;
|
||||
|
||||
usb_id: misc@900 {
|
||||
usb_id: usb-detect@900 {
|
||||
compatible = "qcom,pm8941-misc";
|
||||
reg = <0x900>;
|
||||
interrupts = <0x0 0x9 0 IRQ_TYPE_EDGE_BOTH>;
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ properties:
|
|||
headphone detect mode to HPDETL, ARIZONA_ACCDET_MODE_HPR/2 sets it
|
||||
to HPDETR. If this node is not included or if the value is unknown,
|
||||
then headphone detection mode is set to HPDETL.
|
||||
$ref: "/schemas/types.yaml#/definitions/uint32"
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
minimum: 1
|
||||
maximum: 2
|
||||
|
||||
|
|
@ -51,7 +51,7 @@ properties:
|
|||
description:
|
||||
Additional software microphone detection debounce specified in
|
||||
milliseconds.
|
||||
$ref: "/schemas/types.yaml#/definitions/uint32"
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
|
||||
wlf,micd-pol-gpio:
|
||||
description:
|
||||
|
|
@ -63,7 +63,7 @@ properties:
|
|||
description:
|
||||
Time allowed for MICBIAS to startup prior to performing microphone
|
||||
detection, specified as per the ARIZONA_MICD_TIME_XXX defines.
|
||||
$ref: "/schemas/types.yaml#/definitions/uint32"
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
minimum: 0
|
||||
maximum: 12
|
||||
|
||||
|
|
@ -71,7 +71,7 @@ properties:
|
|||
description:
|
||||
Delay between successive microphone detection measurements, specified
|
||||
as per the ARIZONA_MICD_TIME_XXX defines.
|
||||
$ref: "/schemas/types.yaml#/definitions/uint32"
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
minimum: 0
|
||||
maximum: 12
|
||||
|
||||
|
|
@ -79,7 +79,7 @@ properties:
|
|||
description:
|
||||
Microphone detection hardware debounces specified as the number of
|
||||
measurements to take.
|
||||
$ref: "/schemas/types.yaml#/definitions/uint32"
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
enum: [2, 4]
|
||||
|
||||
wlf,micd-timeout-ms:
|
||||
|
|
@ -97,7 +97,7 @@ properties:
|
|||
CTIA / OMTP headsets), the field can be of variable length but
|
||||
should always be a multiple of 3 cells long, each three cell group
|
||||
represents one polarity configuration.
|
||||
$ref: "/schemas/types.yaml#/definitions/uint32-matrix"
|
||||
$ref: /schemas/types.yaml#/definitions/uint32-matrix
|
||||
items:
|
||||
items:
|
||||
- description:
|
||||
|
|
@ -119,7 +119,7 @@ properties:
|
|||
description:
|
||||
Settings for the general purpose switch, set as one of the
|
||||
ARIZONA_GPSW_XXX defines.
|
||||
$ref: "/schemas/types.yaml#/definitions/uint32"
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
minimum: 0
|
||||
maximum: 3
|
||||
|
||||
|
|
|
|||
|
|
@ -185,6 +185,7 @@ config EXTCON_USBC_TUSB320
|
|||
tristate "TI TUSB320 USB-C extcon support"
|
||||
depends on I2C && TYPEC
|
||||
select REGMAP_I2C
|
||||
depends on USB_ROLE_SWITCH || !USB_ROLE_SWITCH
|
||||
help
|
||||
Say Y here to enable support for USB Type C cable detection extcon
|
||||
support using a TUSB320.
|
||||
|
|
|
|||
|
|
@ -393,7 +393,7 @@ static int axp288_extcon_probe(struct platform_device *pdev)
|
|||
adev = acpi_dev_get_first_match_dev("INT3496", NULL, -1);
|
||||
if (adev) {
|
||||
info->id_extcon = extcon_get_extcon_dev(acpi_dev_name(adev));
|
||||
put_device(&adev->dev);
|
||||
acpi_dev_put(adev);
|
||||
if (IS_ERR(info->id_extcon))
|
||||
return PTR_ERR(info->id_extcon);
|
||||
|
||||
|
|
|
|||
|
|
@ -369,7 +369,7 @@ static struct i2c_driver fsa9480_i2c_driver = {
|
|||
.pm = &fsa9480_pm_ops,
|
||||
.of_match_table = fsa9480_of_match,
|
||||
},
|
||||
.probe_new = fsa9480_probe,
|
||||
.probe = fsa9480_probe,
|
||||
.id_table = fsa9480_id,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -18,7 +18,6 @@
|
|||
#include <linux/mfd/palmas.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/of_gpio.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/workqueue.h>
|
||||
|
||||
|
|
|
|||
|
|
@ -348,7 +348,7 @@ static struct i2c_driver ptn5150_i2c_driver = {
|
|||
.name = "ptn5150",
|
||||
.of_match_table = ptn5150_dt_match,
|
||||
},
|
||||
.probe_new = ptn5150_i2c_probe,
|
||||
.probe = ptn5150_i2c_probe,
|
||||
.id_table = ptn5150_i2c_id,
|
||||
};
|
||||
module_i2c_driver(ptn5150_i2c_driver);
|
||||
|
|
|
|||
|
|
@ -123,7 +123,7 @@ static int qcom_usb_extcon_probe(struct platform_device *pdev)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
info->id_irq = platform_get_irq_byname(pdev, "usb_id");
|
||||
info->id_irq = platform_get_irq_byname_optional(pdev, "usb_id");
|
||||
if (info->id_irq > 0) {
|
||||
ret = devm_request_threaded_irq(dev, info->id_irq, NULL,
|
||||
qcom_usb_irq_handler,
|
||||
|
|
@ -136,7 +136,7 @@ static int qcom_usb_extcon_probe(struct platform_device *pdev)
|
|||
}
|
||||
}
|
||||
|
||||
info->vbus_irq = platform_get_irq_byname(pdev, "usb_vbus");
|
||||
info->vbus_irq = platform_get_irq_byname_optional(pdev, "usb_vbus");
|
||||
if (info->vbus_irq > 0) {
|
||||
ret = devm_request_threaded_irq(dev, info->vbus_irq, NULL,
|
||||
qcom_usb_irq_handler,
|
||||
|
|
|
|||
|
|
@ -695,7 +695,7 @@ static struct i2c_driver rt8973a_muic_i2c_driver = {
|
|||
.pm = &rt8973a_muic_pm_ops,
|
||||
.of_match_table = rt8973a_dt_match,
|
||||
},
|
||||
.probe_new = rt8973a_muic_i2c_probe,
|
||||
.probe = rt8973a_muic_i2c_probe,
|
||||
.remove = rt8973a_muic_i2c_remove,
|
||||
.id_table = rt8973a_i2c_id,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -840,7 +840,7 @@ static struct i2c_driver sm5502_muic_i2c_driver = {
|
|||
.pm = &sm5502_muic_pm_ops,
|
||||
.of_match_table = sm5502_dt_match,
|
||||
},
|
||||
.probe_new = sm5022_muic_i2c_probe,
|
||||
.probe = sm5022_muic_i2c_probe,
|
||||
.id_table = sm5502_i2c_id,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -15,6 +15,8 @@
|
|||
#include <linux/module.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/usb/typec.h>
|
||||
#include <linux/usb/typec_altmode.h>
|
||||
#include <linux/usb/role.h>
|
||||
|
||||
#define TUSB320_REG8 0x8
|
||||
#define TUSB320_REG8_CURRENT_MODE_ADVERTISE GENMASK(7, 6)
|
||||
|
|
@ -26,16 +28,16 @@
|
|||
#define TUSB320_REG8_CURRENT_MODE_DETECT_MED 0x1
|
||||
#define TUSB320_REG8_CURRENT_MODE_DETECT_ACC 0x2
|
||||
#define TUSB320_REG8_CURRENT_MODE_DETECT_HI 0x3
|
||||
#define TUSB320_REG8_ACCESSORY_CONNECTED GENMASK(3, 2)
|
||||
#define TUSB320_REG8_ACCESSORY_CONNECTED GENMASK(3, 1)
|
||||
#define TUSB320_REG8_ACCESSORY_CONNECTED_NONE 0x0
|
||||
#define TUSB320_REG8_ACCESSORY_CONNECTED_AUDIO 0x4
|
||||
#define TUSB320_REG8_ACCESSORY_CONNECTED_ACC 0x5
|
||||
#define TUSB320_REG8_ACCESSORY_CONNECTED_DEBUG 0x6
|
||||
#define TUSB320_REG8_ACCESSORY_CONNECTED_ACHRG 0x5
|
||||
#define TUSB320_REG8_ACCESSORY_CONNECTED_DBGDFP 0x6
|
||||
#define TUSB320_REG8_ACCESSORY_CONNECTED_DBGUFP 0x7
|
||||
#define TUSB320_REG8_ACTIVE_CABLE_DETECTION BIT(0)
|
||||
|
||||
#define TUSB320_REG9 0x9
|
||||
#define TUSB320_REG9_ATTACHED_STATE_SHIFT 6
|
||||
#define TUSB320_REG9_ATTACHED_STATE_MASK 0x3
|
||||
#define TUSB320_REG9_ATTACHED_STATE GENMASK(7, 6)
|
||||
#define TUSB320_REG9_CABLE_DIRECTION BIT(5)
|
||||
#define TUSB320_REG9_INTERRUPT_STATUS BIT(4)
|
||||
|
||||
|
|
@ -78,6 +80,8 @@ struct tusb320_priv {
|
|||
struct typec_capability cap;
|
||||
enum typec_port_type port_type;
|
||||
enum typec_pwr_opmode pwr_opmode;
|
||||
struct fwnode_handle *connector_fwnode;
|
||||
struct usb_role_switch *role_sw;
|
||||
};
|
||||
|
||||
static const char * const tusb_attached_states[] = {
|
||||
|
|
@ -249,8 +253,7 @@ static void tusb320_extcon_irq_handler(struct tusb320_priv *priv, u8 reg)
|
|||
{
|
||||
int state, polarity;
|
||||
|
||||
state = (reg >> TUSB320_REG9_ATTACHED_STATE_SHIFT) &
|
||||
TUSB320_REG9_ATTACHED_STATE_MASK;
|
||||
state = FIELD_GET(TUSB320_REG9_ATTACHED_STATE, reg);
|
||||
polarity = !!(reg & TUSB320_REG9_CABLE_DIRECTION);
|
||||
|
||||
dev_dbg(priv->dev, "attached state: %s, polarity: %d\n",
|
||||
|
|
@ -276,32 +279,86 @@ static void tusb320_typec_irq_handler(struct tusb320_priv *priv, u8 reg9)
|
|||
{
|
||||
struct typec_port *port = priv->port;
|
||||
struct device *dev = priv->dev;
|
||||
u8 mode, role, state;
|
||||
int typec_mode;
|
||||
enum usb_role usb_role;
|
||||
enum typec_role pwr_role;
|
||||
enum typec_data_role data_role;
|
||||
u8 state, mode, accessory;
|
||||
int ret, reg8;
|
||||
bool ori;
|
||||
|
||||
ori = reg9 & TUSB320_REG9_CABLE_DIRECTION;
|
||||
typec_set_orientation(port, ori ? TYPEC_ORIENTATION_REVERSE :
|
||||
TYPEC_ORIENTATION_NORMAL);
|
||||
|
||||
state = (reg9 >> TUSB320_REG9_ATTACHED_STATE_SHIFT) &
|
||||
TUSB320_REG9_ATTACHED_STATE_MASK;
|
||||
if (state == TUSB320_ATTACHED_STATE_DFP)
|
||||
role = TYPEC_SOURCE;
|
||||
else
|
||||
role = TYPEC_SINK;
|
||||
|
||||
typec_set_vconn_role(port, role);
|
||||
typec_set_pwr_role(port, role);
|
||||
typec_set_data_role(port, role == TYPEC_SOURCE ?
|
||||
TYPEC_HOST : TYPEC_DEVICE);
|
||||
|
||||
ret = regmap_read(priv->regmap, TUSB320_REG8, ®8);
|
||||
if (ret) {
|
||||
dev_err(dev, "error during reg8 i2c read, ret=%d!\n", ret);
|
||||
return;
|
||||
}
|
||||
|
||||
ori = reg9 & TUSB320_REG9_CABLE_DIRECTION;
|
||||
typec_set_orientation(port, ori ? TYPEC_ORIENTATION_REVERSE :
|
||||
TYPEC_ORIENTATION_NORMAL);
|
||||
|
||||
state = FIELD_GET(TUSB320_REG9_ATTACHED_STATE, reg9);
|
||||
accessory = FIELD_GET(TUSB320_REG8_ACCESSORY_CONNECTED, reg8);
|
||||
|
||||
switch (state) {
|
||||
case TUSB320_ATTACHED_STATE_DFP:
|
||||
typec_mode = TYPEC_MODE_USB2;
|
||||
usb_role = USB_ROLE_HOST;
|
||||
pwr_role = TYPEC_SOURCE;
|
||||
data_role = TYPEC_HOST;
|
||||
break;
|
||||
case TUSB320_ATTACHED_STATE_UFP:
|
||||
typec_mode = TYPEC_MODE_USB2;
|
||||
usb_role = USB_ROLE_DEVICE;
|
||||
pwr_role = TYPEC_SINK;
|
||||
data_role = TYPEC_DEVICE;
|
||||
break;
|
||||
case TUSB320_ATTACHED_STATE_ACC:
|
||||
/*
|
||||
* Accessory detected. For debug accessories, just make some
|
||||
* qualified guesses as to the role for lack of a better option.
|
||||
*/
|
||||
if (accessory == TUSB320_REG8_ACCESSORY_CONNECTED_AUDIO ||
|
||||
accessory == TUSB320_REG8_ACCESSORY_CONNECTED_ACHRG) {
|
||||
typec_mode = TYPEC_MODE_AUDIO;
|
||||
usb_role = USB_ROLE_NONE;
|
||||
pwr_role = TYPEC_SINK;
|
||||
data_role = TYPEC_DEVICE;
|
||||
break;
|
||||
} else if (accessory ==
|
||||
TUSB320_REG8_ACCESSORY_CONNECTED_DBGDFP) {
|
||||
typec_mode = TYPEC_MODE_DEBUG;
|
||||
pwr_role = TYPEC_SOURCE;
|
||||
usb_role = USB_ROLE_HOST;
|
||||
data_role = TYPEC_HOST;
|
||||
break;
|
||||
} else if (accessory ==
|
||||
TUSB320_REG8_ACCESSORY_CONNECTED_DBGUFP) {
|
||||
typec_mode = TYPEC_MODE_DEBUG;
|
||||
pwr_role = TYPEC_SINK;
|
||||
usb_role = USB_ROLE_DEVICE;
|
||||
data_role = TYPEC_DEVICE;
|
||||
break;
|
||||
}
|
||||
|
||||
dev_warn(priv->dev, "unexpected ACCESSORY_CONNECTED state %d\n",
|
||||
accessory);
|
||||
|
||||
fallthrough;
|
||||
default:
|
||||
typec_mode = TYPEC_MODE_USB2;
|
||||
usb_role = USB_ROLE_NONE;
|
||||
pwr_role = TYPEC_SINK;
|
||||
data_role = TYPEC_DEVICE;
|
||||
break;
|
||||
}
|
||||
|
||||
typec_set_vconn_role(port, pwr_role);
|
||||
typec_set_pwr_role(port, pwr_role);
|
||||
typec_set_data_role(port, data_role);
|
||||
typec_set_mode(port, typec_mode);
|
||||
usb_role_switch_set_role(priv->role_sw, usb_role);
|
||||
|
||||
mode = FIELD_GET(TUSB320_REG8_CURRENT_MODE_DETECT, reg8);
|
||||
if (mode == TUSB320_REG8_CURRENT_MODE_DETECT_DEF)
|
||||
typec_set_pwr_opmode(port, TYPEC_PWR_MODE_USB);
|
||||
|
|
@ -391,27 +448,25 @@ static int tusb320_typec_probe(struct i2c_client *client,
|
|||
/* Type-C connector found. */
|
||||
ret = typec_get_fw_cap(&priv->cap, connector);
|
||||
if (ret)
|
||||
return ret;
|
||||
goto err_put;
|
||||
|
||||
priv->port_type = priv->cap.type;
|
||||
|
||||
/* This goes into register 0x8 field CURRENT_MODE_ADVERTISE */
|
||||
ret = fwnode_property_read_string(connector, "typec-power-opmode", &cap_str);
|
||||
if (ret)
|
||||
return ret;
|
||||
goto err_put;
|
||||
|
||||
ret = typec_find_pwr_opmode(cap_str);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (ret == TYPEC_PWR_MODE_PD)
|
||||
return -EINVAL;
|
||||
goto err_put;
|
||||
|
||||
priv->pwr_opmode = ret;
|
||||
|
||||
/* Initialize the hardware with the devicetree settings. */
|
||||
ret = tusb320_set_adv_pwr_mode(priv);
|
||||
if (ret)
|
||||
return ret;
|
||||
goto err_put;
|
||||
|
||||
priv->cap.revision = USB_TYPEC_REV_1_1;
|
||||
priv->cap.accessory[0] = TYPEC_ACCESSORY_AUDIO;
|
||||
|
|
@ -422,10 +477,36 @@ static int tusb320_typec_probe(struct i2c_client *client,
|
|||
priv->cap.fwnode = connector;
|
||||
|
||||
priv->port = typec_register_port(&client->dev, &priv->cap);
|
||||
if (IS_ERR(priv->port))
|
||||
return PTR_ERR(priv->port);
|
||||
if (IS_ERR(priv->port)) {
|
||||
ret = PTR_ERR(priv->port);
|
||||
goto err_put;
|
||||
}
|
||||
|
||||
/* Find any optional USB role switch that needs reporting to */
|
||||
priv->role_sw = fwnode_usb_role_switch_get(connector);
|
||||
if (IS_ERR(priv->role_sw)) {
|
||||
ret = PTR_ERR(priv->role_sw);
|
||||
goto err_unreg;
|
||||
}
|
||||
|
||||
priv->connector_fwnode = connector;
|
||||
|
||||
return 0;
|
||||
|
||||
err_unreg:
|
||||
typec_unregister_port(priv->port);
|
||||
|
||||
err_put:
|
||||
fwnode_handle_put(connector);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void tusb320_typec_remove(struct tusb320_priv *priv)
|
||||
{
|
||||
usb_role_switch_put(priv->role_sw);
|
||||
typec_unregister_port(priv->port);
|
||||
fwnode_handle_put(priv->connector_fwnode);
|
||||
}
|
||||
|
||||
static int tusb320_probe(struct i2c_client *client)
|
||||
|
|
@ -438,7 +519,9 @@ static int tusb320_probe(struct i2c_client *client)
|
|||
priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL);
|
||||
if (!priv)
|
||||
return -ENOMEM;
|
||||
|
||||
priv->dev = &client->dev;
|
||||
i2c_set_clientdata(client, priv);
|
||||
|
||||
priv->regmap = devm_regmap_init_i2c(client, &tusb320_regmap_config);
|
||||
if (IS_ERR(priv->regmap))
|
||||
|
|
@ -489,10 +572,19 @@ static int tusb320_probe(struct i2c_client *client)
|
|||
tusb320_irq_handler,
|
||||
IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
|
||||
client->name, priv);
|
||||
if (ret)
|
||||
tusb320_typec_remove(priv);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void tusb320_remove(struct i2c_client *client)
|
||||
{
|
||||
struct tusb320_priv *priv = i2c_get_clientdata(client);
|
||||
|
||||
tusb320_typec_remove(priv);
|
||||
}
|
||||
|
||||
static const struct of_device_id tusb320_extcon_dt_match[] = {
|
||||
{ .compatible = "ti,tusb320", .data = &tusb320_ops, },
|
||||
{ .compatible = "ti,tusb320l", .data = &tusb320l_ops, },
|
||||
|
|
@ -501,7 +593,8 @@ static const struct of_device_id tusb320_extcon_dt_match[] = {
|
|||
MODULE_DEVICE_TABLE(of, tusb320_extcon_dt_match);
|
||||
|
||||
static struct i2c_driver tusb320_extcon_driver = {
|
||||
.probe_new = tusb320_probe,
|
||||
.probe = tusb320_probe,
|
||||
.remove = tusb320_remove,
|
||||
.driver = {
|
||||
.name = "extcon-tusb320",
|
||||
.of_match_table = tusb320_extcon_dt_match,
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
#include <linux/module.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/idr.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/fs.h>
|
||||
|
|
@ -206,6 +207,14 @@ static const struct __extcon_info {
|
|||
* @attr_name: "name" sysfs entry
|
||||
* @attr_state: "state" sysfs entry
|
||||
* @attrs: the array pointing to attr_name and attr_state for attr_g
|
||||
* @usb_propval: the array of USB connector properties
|
||||
* @chg_propval: the array of charger connector properties
|
||||
* @jack_propval: the array of jack connector properties
|
||||
* @disp_propval: the array of display connector properties
|
||||
* @usb_bits: the bit array of the USB connector property capabilities
|
||||
* @chg_bits: the bit array of the charger connector property capabilities
|
||||
* @jack_bits: the bit array of the jack connector property capabilities
|
||||
* @disp_bits: the bit array of the display connector property capabilities
|
||||
*/
|
||||
struct extcon_cable {
|
||||
struct extcon_dev *edev;
|
||||
|
|
@ -222,20 +231,21 @@ struct extcon_cable {
|
|||
union extcon_property_value jack_propval[EXTCON_PROP_JACK_CNT];
|
||||
union extcon_property_value disp_propval[EXTCON_PROP_DISP_CNT];
|
||||
|
||||
unsigned long usb_bits[BITS_TO_LONGS(EXTCON_PROP_USB_CNT)];
|
||||
unsigned long chg_bits[BITS_TO_LONGS(EXTCON_PROP_CHG_CNT)];
|
||||
unsigned long jack_bits[BITS_TO_LONGS(EXTCON_PROP_JACK_CNT)];
|
||||
unsigned long disp_bits[BITS_TO_LONGS(EXTCON_PROP_DISP_CNT)];
|
||||
DECLARE_BITMAP(usb_bits, EXTCON_PROP_USB_CNT);
|
||||
DECLARE_BITMAP(chg_bits, EXTCON_PROP_CHG_CNT);
|
||||
DECLARE_BITMAP(jack_bits, EXTCON_PROP_JACK_CNT);
|
||||
DECLARE_BITMAP(disp_bits, EXTCON_PROP_DISP_CNT);
|
||||
};
|
||||
|
||||
static struct class *extcon_class;
|
||||
|
||||
static DEFINE_IDA(extcon_dev_ids);
|
||||
static LIST_HEAD(extcon_dev_list);
|
||||
static DEFINE_MUTEX(extcon_dev_list_lock);
|
||||
|
||||
static int check_mutually_exclusive(struct extcon_dev *edev, u32 new_state)
|
||||
{
|
||||
int i = 0;
|
||||
int i;
|
||||
|
||||
if (!edev->mutually_exclusive)
|
||||
return 0;
|
||||
|
|
@ -362,12 +372,12 @@ static ssize_t state_show(struct device *dev, struct device_attribute *attr,
|
|||
struct extcon_dev *edev = dev_get_drvdata(dev);
|
||||
|
||||
if (edev->max_supported == 0)
|
||||
return sprintf(buf, "%u\n", edev->state);
|
||||
return sysfs_emit(buf, "%u\n", edev->state);
|
||||
|
||||
for (i = 0; i < edev->max_supported; i++) {
|
||||
count += sprintf(buf + count, "%s=%d\n",
|
||||
extcon_info[edev->supported_cable[i]].name,
|
||||
!!(edev->state & BIT(i)));
|
||||
count += sysfs_emit_at(buf, count, "%s=%d\n",
|
||||
extcon_info[edev->supported_cable[i]].name,
|
||||
!!(edev->state & BIT(i)));
|
||||
}
|
||||
|
||||
return count;
|
||||
|
|
@ -379,7 +389,7 @@ static ssize_t name_show(struct device *dev, struct device_attribute *attr,
|
|||
{
|
||||
struct extcon_dev *edev = dev_get_drvdata(dev);
|
||||
|
||||
return sprintf(buf, "%s\n", edev->name);
|
||||
return sysfs_emit(buf, "%s\n", edev->name);
|
||||
}
|
||||
static DEVICE_ATTR_RO(name);
|
||||
|
||||
|
|
@ -390,8 +400,8 @@ static ssize_t cable_name_show(struct device *dev,
|
|||
attr_name);
|
||||
int i = cable->cable_index;
|
||||
|
||||
return sprintf(buf, "%s\n",
|
||||
extcon_info[cable->edev->supported_cable[i]].name);
|
||||
return sysfs_emit(buf, "%s\n",
|
||||
extcon_info[cable->edev->supported_cable[i]].name);
|
||||
}
|
||||
|
||||
static ssize_t cable_state_show(struct device *dev,
|
||||
|
|
@ -402,8 +412,8 @@ static ssize_t cable_state_show(struct device *dev,
|
|||
|
||||
int i = cable->cable_index;
|
||||
|
||||
return sprintf(buf, "%d\n",
|
||||
extcon_get_state(cable->edev, cable->edev->supported_cable[i]));
|
||||
return sysfs_emit(buf, "%d\n",
|
||||
extcon_get_state(cable->edev, cable->edev->supported_cable[i]));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1012,12 +1022,13 @@ ATTRIBUTE_GROUPS(extcon);
|
|||
|
||||
static int create_extcon_class(void)
|
||||
{
|
||||
if (!extcon_class) {
|
||||
extcon_class = class_create("extcon");
|
||||
if (IS_ERR(extcon_class))
|
||||
return PTR_ERR(extcon_class);
|
||||
extcon_class->dev_groups = extcon_groups;
|
||||
}
|
||||
if (extcon_class)
|
||||
return 0;
|
||||
|
||||
extcon_class = class_create("extcon");
|
||||
if (IS_ERR(extcon_class))
|
||||
return PTR_ERR(extcon_class);
|
||||
extcon_class->dev_groups = extcon_groups;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1069,6 +1080,156 @@ void extcon_dev_free(struct extcon_dev *edev)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(extcon_dev_free);
|
||||
|
||||
/**
|
||||
* extcon_alloc_cables() - alloc the cables for extcon device
|
||||
* @edev: extcon device which has cables
|
||||
*
|
||||
* Returns 0 if success or error number if fail.
|
||||
*/
|
||||
static int extcon_alloc_cables(struct extcon_dev *edev)
|
||||
{
|
||||
int index;
|
||||
char *str;
|
||||
struct extcon_cable *cable;
|
||||
|
||||
if (!edev)
|
||||
return -EINVAL;
|
||||
|
||||
if (!edev->max_supported)
|
||||
return 0;
|
||||
|
||||
edev->cables = kcalloc(edev->max_supported, sizeof(*edev->cables),
|
||||
GFP_KERNEL);
|
||||
if (!edev->cables)
|
||||
return -ENOMEM;
|
||||
|
||||
for (index = 0; index < edev->max_supported; index++) {
|
||||
cable = &edev->cables[index];
|
||||
|
||||
str = kasprintf(GFP_KERNEL, "cable.%d", index);
|
||||
if (!str) {
|
||||
for (index--; index >= 0; index--) {
|
||||
cable = &edev->cables[index];
|
||||
kfree(cable->attr_g.name);
|
||||
}
|
||||
|
||||
kfree(edev->cables);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
cable->edev = edev;
|
||||
cable->cable_index = index;
|
||||
cable->attrs[0] = &cable->attr_name.attr;
|
||||
cable->attrs[1] = &cable->attr_state.attr;
|
||||
cable->attrs[2] = NULL;
|
||||
cable->attr_g.name = str;
|
||||
cable->attr_g.attrs = cable->attrs;
|
||||
|
||||
sysfs_attr_init(&cable->attr_name.attr);
|
||||
cable->attr_name.attr.name = "name";
|
||||
cable->attr_name.attr.mode = 0444;
|
||||
cable->attr_name.show = cable_name_show;
|
||||
|
||||
sysfs_attr_init(&cable->attr_state.attr);
|
||||
cable->attr_state.attr.name = "state";
|
||||
cable->attr_state.attr.mode = 0444;
|
||||
cable->attr_state.show = cable_state_show;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* extcon_alloc_muex() - alloc the mutual exclusive for extcon device
|
||||
* @edev: extcon device
|
||||
*
|
||||
* Returns 0 if success or error number if fail.
|
||||
*/
|
||||
static int extcon_alloc_muex(struct extcon_dev *edev)
|
||||
{
|
||||
char *name;
|
||||
int index;
|
||||
|
||||
if (!edev)
|
||||
return -EINVAL;
|
||||
|
||||
if (!(edev->max_supported && edev->mutually_exclusive))
|
||||
return 0;
|
||||
|
||||
/* Count the size of mutually_exclusive array */
|
||||
for (index = 0; edev->mutually_exclusive[index]; index++)
|
||||
;
|
||||
|
||||
edev->attrs_muex = kcalloc(index + 1, sizeof(*edev->attrs_muex),
|
||||
GFP_KERNEL);
|
||||
if (!edev->attrs_muex)
|
||||
return -ENOMEM;
|
||||
|
||||
edev->d_attrs_muex = kcalloc(index, sizeof(*edev->d_attrs_muex),
|
||||
GFP_KERNEL);
|
||||
if (!edev->d_attrs_muex) {
|
||||
kfree(edev->attrs_muex);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
for (index = 0; edev->mutually_exclusive[index]; index++) {
|
||||
name = kasprintf(GFP_KERNEL, "0x%x",
|
||||
edev->mutually_exclusive[index]);
|
||||
if (!name) {
|
||||
for (index--; index >= 0; index--)
|
||||
kfree(edev->d_attrs_muex[index].attr.name);
|
||||
|
||||
kfree(edev->d_attrs_muex);
|
||||
kfree(edev->attrs_muex);
|
||||
return -ENOMEM;
|
||||
}
|
||||
sysfs_attr_init(&edev->d_attrs_muex[index].attr);
|
||||
edev->d_attrs_muex[index].attr.name = name;
|
||||
edev->d_attrs_muex[index].attr.mode = 0000;
|
||||
edev->attrs_muex[index] = &edev->d_attrs_muex[index].attr;
|
||||
}
|
||||
edev->attr_g_muex.name = muex_name;
|
||||
edev->attr_g_muex.attrs = edev->attrs_muex;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* extcon_alloc_groups() - alloc the groups for extcon device
|
||||
* @edev: extcon device
|
||||
*
|
||||
* Returns 0 if success or error number if fail.
|
||||
*/
|
||||
static int extcon_alloc_groups(struct extcon_dev *edev)
|
||||
{
|
||||
int index;
|
||||
|
||||
if (!edev)
|
||||
return -EINVAL;
|
||||
|
||||
if (!edev->max_supported)
|
||||
return 0;
|
||||
|
||||
edev->extcon_dev_type.groups = kcalloc(edev->max_supported + 2,
|
||||
sizeof(*edev->extcon_dev_type.groups),
|
||||
GFP_KERNEL);
|
||||
if (!edev->extcon_dev_type.groups)
|
||||
return -ENOMEM;
|
||||
|
||||
edev->extcon_dev_type.name = dev_name(&edev->dev);
|
||||
edev->extcon_dev_type.release = dummy_sysfs_dev_release;
|
||||
|
||||
for (index = 0; index < edev->max_supported; index++)
|
||||
edev->extcon_dev_type.groups[index] = &edev->cables[index].attr_g;
|
||||
|
||||
if (edev->mutually_exclusive)
|
||||
edev->extcon_dev_type.groups[index] = &edev->attr_g_muex;
|
||||
|
||||
edev->dev.type = &edev->extcon_dev_type;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* extcon_dev_register() - Register an new extcon device
|
||||
* @edev: the extcon device to be registered
|
||||
|
|
@ -1085,19 +1246,16 @@ EXPORT_SYMBOL_GPL(extcon_dev_free);
|
|||
*/
|
||||
int extcon_dev_register(struct extcon_dev *edev)
|
||||
{
|
||||
int ret, index = 0;
|
||||
static atomic_t edev_no = ATOMIC_INIT(-1);
|
||||
int ret, index;
|
||||
|
||||
if (!extcon_class) {
|
||||
ret = create_extcon_class();
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
ret = create_extcon_class();
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (!edev || !edev->supported_cable)
|
||||
return -EINVAL;
|
||||
|
||||
for (; edev->supported_cable[index] != EXTCON_NONE; index++);
|
||||
for (index = 0; edev->supported_cable[index] != EXTCON_NONE; index++);
|
||||
|
||||
edev->max_supported = index;
|
||||
if (index > SUPPORTED_CABLE_MAX) {
|
||||
|
|
@ -1115,124 +1273,26 @@ int extcon_dev_register(struct extcon_dev *edev)
|
|||
"extcon device name is null\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
dev_set_name(&edev->dev, "extcon%lu",
|
||||
(unsigned long)atomic_inc_return(&edev_no));
|
||||
|
||||
if (edev->max_supported) {
|
||||
char *str;
|
||||
struct extcon_cable *cable;
|
||||
ret = ida_alloc(&extcon_dev_ids, GFP_KERNEL);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
edev->cables = kcalloc(edev->max_supported,
|
||||
sizeof(struct extcon_cable),
|
||||
GFP_KERNEL);
|
||||
if (!edev->cables) {
|
||||
ret = -ENOMEM;
|
||||
goto err_sysfs_alloc;
|
||||
}
|
||||
for (index = 0; index < edev->max_supported; index++) {
|
||||
cable = &edev->cables[index];
|
||||
edev->id = ret;
|
||||
|
||||
str = kasprintf(GFP_KERNEL, "cable.%d", index);
|
||||
if (!str) {
|
||||
for (index--; index >= 0; index--) {
|
||||
cable = &edev->cables[index];
|
||||
kfree(cable->attr_g.name);
|
||||
}
|
||||
ret = -ENOMEM;
|
||||
dev_set_name(&edev->dev, "extcon%d", edev->id);
|
||||
|
||||
goto err_alloc_cables;
|
||||
}
|
||||
ret = extcon_alloc_cables(edev);
|
||||
if (ret < 0)
|
||||
goto err_alloc_cables;
|
||||
|
||||
cable->edev = edev;
|
||||
cable->cable_index = index;
|
||||
cable->attrs[0] = &cable->attr_name.attr;
|
||||
cable->attrs[1] = &cable->attr_state.attr;
|
||||
cable->attrs[2] = NULL;
|
||||
cable->attr_g.name = str;
|
||||
cable->attr_g.attrs = cable->attrs;
|
||||
ret = extcon_alloc_muex(edev);
|
||||
if (ret < 0)
|
||||
goto err_alloc_muex;
|
||||
|
||||
sysfs_attr_init(&cable->attr_name.attr);
|
||||
cable->attr_name.attr.name = "name";
|
||||
cable->attr_name.attr.mode = 0444;
|
||||
cable->attr_name.show = cable_name_show;
|
||||
|
||||
sysfs_attr_init(&cable->attr_state.attr);
|
||||
cable->attr_state.attr.name = "state";
|
||||
cable->attr_state.attr.mode = 0444;
|
||||
cable->attr_state.show = cable_state_show;
|
||||
}
|
||||
}
|
||||
|
||||
if (edev->max_supported && edev->mutually_exclusive) {
|
||||
char *name;
|
||||
|
||||
/* Count the size of mutually_exclusive array */
|
||||
for (index = 0; edev->mutually_exclusive[index]; index++)
|
||||
;
|
||||
|
||||
edev->attrs_muex = kcalloc(index + 1,
|
||||
sizeof(struct attribute *),
|
||||
GFP_KERNEL);
|
||||
if (!edev->attrs_muex) {
|
||||
ret = -ENOMEM;
|
||||
goto err_muex;
|
||||
}
|
||||
|
||||
edev->d_attrs_muex = kcalloc(index,
|
||||
sizeof(struct device_attribute),
|
||||
GFP_KERNEL);
|
||||
if (!edev->d_attrs_muex) {
|
||||
ret = -ENOMEM;
|
||||
kfree(edev->attrs_muex);
|
||||
goto err_muex;
|
||||
}
|
||||
|
||||
for (index = 0; edev->mutually_exclusive[index]; index++) {
|
||||
name = kasprintf(GFP_KERNEL, "0x%x",
|
||||
edev->mutually_exclusive[index]);
|
||||
if (!name) {
|
||||
for (index--; index >= 0; index--) {
|
||||
kfree(edev->d_attrs_muex[index].attr.
|
||||
name);
|
||||
}
|
||||
kfree(edev->d_attrs_muex);
|
||||
kfree(edev->attrs_muex);
|
||||
ret = -ENOMEM;
|
||||
goto err_muex;
|
||||
}
|
||||
sysfs_attr_init(&edev->d_attrs_muex[index].attr);
|
||||
edev->d_attrs_muex[index].attr.name = name;
|
||||
edev->d_attrs_muex[index].attr.mode = 0000;
|
||||
edev->attrs_muex[index] = &edev->d_attrs_muex[index]
|
||||
.attr;
|
||||
}
|
||||
edev->attr_g_muex.name = muex_name;
|
||||
edev->attr_g_muex.attrs = edev->attrs_muex;
|
||||
|
||||
}
|
||||
|
||||
if (edev->max_supported) {
|
||||
edev->extcon_dev_type.groups =
|
||||
kcalloc(edev->max_supported + 2,
|
||||
sizeof(struct attribute_group *),
|
||||
GFP_KERNEL);
|
||||
if (!edev->extcon_dev_type.groups) {
|
||||
ret = -ENOMEM;
|
||||
goto err_alloc_groups;
|
||||
}
|
||||
|
||||
edev->extcon_dev_type.name = dev_name(&edev->dev);
|
||||
edev->extcon_dev_type.release = dummy_sysfs_dev_release;
|
||||
|
||||
for (index = 0; index < edev->max_supported; index++)
|
||||
edev->extcon_dev_type.groups[index] =
|
||||
&edev->cables[index].attr_g;
|
||||
if (edev->mutually_exclusive)
|
||||
edev->extcon_dev_type.groups[index] =
|
||||
&edev->attr_g_muex;
|
||||
|
||||
edev->dev.type = &edev->extcon_dev_type;
|
||||
}
|
||||
ret = extcon_alloc_groups(edev);
|
||||
if (ret < 0)
|
||||
goto err_alloc_groups;
|
||||
|
||||
spin_lock_init(&edev->lock);
|
||||
if (edev->max_supported) {
|
||||
|
|
@ -1277,13 +1337,14 @@ int extcon_dev_register(struct extcon_dev *edev)
|
|||
kfree(edev->d_attrs_muex);
|
||||
kfree(edev->attrs_muex);
|
||||
}
|
||||
err_muex:
|
||||
err_alloc_muex:
|
||||
for (index = 0; index < edev->max_supported; index++)
|
||||
kfree(edev->cables[index].attr_g.name);
|
||||
err_alloc_cables:
|
||||
if (edev->max_supported)
|
||||
kfree(edev->cables);
|
||||
err_sysfs_alloc:
|
||||
err_alloc_cables:
|
||||
ida_free(&extcon_dev_ids, edev->id);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(extcon_dev_register);
|
||||
|
|
@ -1306,12 +1367,13 @@ void extcon_dev_unregister(struct extcon_dev *edev)
|
|||
list_del(&edev->entry);
|
||||
mutex_unlock(&extcon_dev_list_lock);
|
||||
|
||||
if (IS_ERR_OR_NULL(get_device(&edev->dev))) {
|
||||
dev_err(&edev->dev, "Failed to unregister extcon_dev (%s)\n",
|
||||
dev_name(&edev->dev));
|
||||
if (!get_device(&edev->dev)) {
|
||||
dev_err(&edev->dev, "Failed to unregister extcon_dev\n");
|
||||
return;
|
||||
}
|
||||
|
||||
ida_free(&extcon_dev_ids, edev->id);
|
||||
|
||||
device_unregister(&edev->dev);
|
||||
|
||||
if (edev->mutually_exclusive && edev->max_supported) {
|
||||
|
|
@ -1349,7 +1411,7 @@ struct extcon_dev *extcon_find_edev_by_node(struct device_node *node)
|
|||
|
||||
mutex_lock(&extcon_dev_list_lock);
|
||||
list_for_each_entry(edev, &extcon_dev_list, entry)
|
||||
if (edev->dev.parent && edev->dev.parent->of_node == node)
|
||||
if (edev->dev.parent && device_match_of_node(edev->dev.parent, node))
|
||||
goto out;
|
||||
edev = ERR_PTR(-EPROBE_DEFER);
|
||||
out:
|
||||
|
|
@ -1367,21 +1429,17 @@ struct extcon_dev *extcon_find_edev_by_node(struct device_node *node)
|
|||
*/
|
||||
struct extcon_dev *extcon_get_edev_by_phandle(struct device *dev, int index)
|
||||
{
|
||||
struct device_node *node;
|
||||
struct device_node *node, *np = dev_of_node(dev);
|
||||
struct extcon_dev *edev;
|
||||
|
||||
if (!dev)
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
if (!dev->of_node) {
|
||||
if (!np) {
|
||||
dev_dbg(dev, "device does not have a device node entry\n");
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
node = of_parse_phandle(dev->of_node, "extcon", index);
|
||||
node = of_parse_phandle(np, "extcon", index);
|
||||
if (!node) {
|
||||
dev_dbg(dev, "failed to get phandle in %pOF node\n",
|
||||
dev->of_node);
|
||||
dev_dbg(dev, "failed to get phandle in %pOF node\n", np);
|
||||
return ERR_PTR(-ENODEV);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -13,13 +13,14 @@
|
|||
* are disabled.
|
||||
* @mutually_exclusive: Array of mutually exclusive set of cables that cannot
|
||||
* be attached simultaneously. The array should be
|
||||
* ending with NULL or be NULL (no mutually exclusive
|
||||
* cables). For example, if it is { 0x7, 0x30, 0}, then,
|
||||
* ending with 0 or be NULL (no mutually exclusive cables).
|
||||
* For example, if it is {0x7, 0x30, 0}, then,
|
||||
* {0, 1}, {0, 1, 2}, {0, 2}, {1, 2}, or {4, 5} cannot
|
||||
* be attached simulataneously. {0x7, 0} is equivalent to
|
||||
* {0x3, 0x6, 0x5, 0}. If it is {0xFFFFFFFF, 0}, there
|
||||
* can be no simultaneous connections.
|
||||
* @dev: Device of this extcon.
|
||||
* @id: Unique device ID of this extcon.
|
||||
* @state: Attach/detach state of this extcon. Do not provide at
|
||||
* register-time.
|
||||
* @nh_all: Notifier for the state change events for all supported
|
||||
|
|
@ -27,7 +28,7 @@
|
|||
* @nh: Notifier for the state change events from this extcon
|
||||
* @entry: To support list of extcon devices so that users can
|
||||
* search for extcon devices based on the extcon name.
|
||||
* @lock:
|
||||
* @lock: Protects device state and serialises device registration
|
||||
* @max_supported: Internal value to store the number of cables.
|
||||
* @extcon_dev_type: Device_type struct to provide attribute_groups
|
||||
* customized for each extcon device.
|
||||
|
|
@ -46,6 +47,7 @@ struct extcon_dev {
|
|||
|
||||
/* Internal data. Please do not set. */
|
||||
struct device dev;
|
||||
unsigned int id;
|
||||
struct raw_notifier_head nh_all;
|
||||
struct raw_notifier_head *nh;
|
||||
struct list_head entry;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user