usb: typec: Add typec_get_driver_from_usb() API

The typec_get_driver_from_usb() allows to retrieve a Type-C device from
an USB device.
typec_get_driver_from_usb() checks in USB device node for port and endpoint
sub-node, if exist, retrieve the connector node, probe the associated
Type-C device and return it.

Signed-off-by: Patrice Chotard <patrice.chotard@foss.st.com>
Change-Id: If564cdf463f3915bec26f17a4717c9ab9d42f692
Reviewed-on: https://gerrit.st.com/c/mpu/oe/st/u-boot/+/232353
Reviewed-by: CITOOLS <MDG-smet-aci-reviews@list.st.com>
Reviewed-by: Patrick DELAUNAY <patrick.delaunay@foss.st.com>
This commit is contained in:
Patrice Chotard
2021-11-09 16:49:38 +01:00
parent 7eeb19f152
commit d7cf053394
2 changed files with 134 additions and 1 deletions

View File

@ -10,6 +10,74 @@
#include <errno.h>
#include <typec.h>
#include <dm/device_compat.h>
#include <dm/device-internal.h>
#include <dm/uclass-internal.h>
int typec_get_device_from_usb(struct udevice *dev, struct udevice **typec, u8 index)
{
ofnode node, child;
u32 endpoint_phandle;
u32 reg;
int ret;
/* 'port' nodes can be grouped under an optional 'ports' node */
node = dev_read_subnode(dev, "ports");
if (!ofnode_valid(node)) {
node = dev_read_subnode(dev, "port");
} else {
/* several 'port' nodes, found the requested port@index one */
ofnode_for_each_subnode(child, node) {
ofnode_read_u32(child, "reg", &reg);
if (index == reg) {
node = child;
break;
}
}
node = child;
}
if (!ofnode_valid(node)) {
dev_dbg(dev, "connector port or port@%d subnode not found\n", index);
return -ENODEV;
}
/* get endpoint node */
node = ofnode_first_subnode(node);
if (!ofnode_valid(node))
return -EINVAL;
ret = ofnode_read_u32(node, "remote-endpoint", &endpoint_phandle);
if (ret)
return ret;
/* retrieve connector endpoint phandle */
node = ofnode_get_by_phandle(endpoint_phandle);
if (!ofnode_valid(node))
return -EINVAL;
/*
* Use a while to retrieve an USB Type-C device either at connector
* level or just above (depending if UCSI uclass is used or not)
*/
while (ofnode_valid(node)) {
node = ofnode_get_parent(node);
if (!ofnode_valid(node)) {
dev_err(dev, "No UCLASS_USB_TYPEC for remote-endpoint\n");
return -EINVAL;
}
uclass_find_device_by_ofnode(UCLASS_USB_TYPEC, node, typec);
if (*typec)
break;
}
ret = device_probe(*typec);
if (ret) {
dev_err(dev, "Type-C won't probe (ret=%d)\n", ret);
return ret;
}
return 0;
}
int typec_get_data_role(struct udevice *dev, u8 con_idx)
{

View File

@ -70,6 +70,66 @@ int typec_get_data_role(struct udevice *dev, u8 con_idx);
* @return Type-C connector number or -ve on error.
*/
int typec_get_nb_connector(struct udevice *dev);
/**
* typec_get_device_from_usb() - Allows to retrieve a Type-C device from
* an USB device. typec_get_driver_from_usb() checks in USB device node
* for port and endpoint sub-node, if exist, retrieve the connector node,
* probe the associated Type-C device and return it (see DT example below).
* See Documentation/devicetree/bindings/connector/usb-connector.yaml for more
* details
*
* @dev: USB device
* @typec: Type-C device
* @index: USB controller port number
* @return -ve on error.
*
* usb_dwc3_0: usb@10000000 {
* ...
* port@0 {
* reg = <0>;
* typec_hs: endpoint {
* remote-endpoint = <&usb_con_hs>;
* };
* };
*
* port@1 {
* reg = <1>;
* typec_ss: endpoint {
* remote-endpoint = <&usb_con_ss>;
* };
* };
* };
*
* usb-typec@1 {
* ...
* connector {
* compatible = "usb-c-connector";
* label = "USB-C";
*
* ports {
* #address-cells = <1>;
* #size-cells = <0>;
*
* port@0 {
* reg = <0>;
* usb_con_hs: endpoint {
* remote-endpoint = <&typec_hs>;
* };
* };
*
* port@1 {
* reg = <1>;
* usb_con_ss: endpoint {
* remote-endpoint = <&typec_ss>;
* };
* };
* };
* };
* };
*/
int typec_get_device_from_usb(struct udevice *dev, struct udevice **typec, u8
index);
#else
static inline int typec_is_attached(struct udevice *dev, u8 con_idx)
{
@ -85,5 +145,10 @@ static inline int typec_get_nb_connector(struct udevice *dev)
{
return -EINVAL;
}
#endif
static inline int typec_get_device_from_usb(struct udevice *dev, struct udevice **typec,
u8 index)
{
return -ENODEV;
}
#endif