platform/chrome: cros_ec_typec: Register port altmodes
Instead of using manually managed altmode structs, register the port's altmodes with the Type-C framework. This facilitates matching them to partner altmodes later. Cc: Heikki Krogerus <heikki.krogerus@linux.intel.com> Signed-off-by: Prashant Malani <pmalani@chromium.org> Acked-by: Heikki Krogerus <heikki.krogerus@linux.intel.com> Link: https://lore.kernel.org/r/20220712210318.2671292-2-pmalani@chromium.org
This commit is contained in:
parent
a47bc5a0c4
commit
1ff5d97f07
1 changed files with 40 additions and 11 deletions
|
@ -25,6 +25,8 @@
|
||||||
|
|
||||||
#define DRV_NAME "cros-ec-typec"
|
#define DRV_NAME "cros-ec-typec"
|
||||||
|
|
||||||
|
#define DP_PORT_VDO (BIT(DP_PIN_ASSIGN_C) | BIT(DP_PIN_ASSIGN_D) | DP_CAP_DFP_D)
|
||||||
|
|
||||||
/* Supported alt modes. */
|
/* Supported alt modes. */
|
||||||
enum {
|
enum {
|
||||||
CROS_EC_ALTMODE_DP = 0,
|
CROS_EC_ALTMODE_DP = 0,
|
||||||
|
@ -60,7 +62,7 @@ struct cros_typec_port {
|
||||||
uint8_t mux_flags;
|
uint8_t mux_flags;
|
||||||
uint8_t role;
|
uint8_t role;
|
||||||
|
|
||||||
struct typec_altmode port_altmode[CROS_EC_ALTMODE_MAX];
|
struct typec_altmode *port_altmode[CROS_EC_ALTMODE_MAX];
|
||||||
|
|
||||||
/* Flag indicating that PD partner discovery data parsing is completed. */
|
/* Flag indicating that PD partner discovery data parsing is completed. */
|
||||||
bool sop_disc_done;
|
bool sop_disc_done;
|
||||||
|
@ -253,6 +255,14 @@ static void cros_typec_remove_cable(struct cros_typec_data *typec,
|
||||||
port->sop_prime_disc_done = false;
|
port->sop_prime_disc_done = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void cros_typec_unregister_port_altmodes(struct cros_typec_port *port)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < CROS_EC_ALTMODE_MAX; i++)
|
||||||
|
typec_unregister_altmode(port->port_altmode[i]);
|
||||||
|
}
|
||||||
|
|
||||||
static void cros_unregister_ports(struct cros_typec_data *typec)
|
static void cros_unregister_ports(struct cros_typec_data *typec)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
@ -267,34 +277,49 @@ static void cros_unregister_ports(struct cros_typec_data *typec)
|
||||||
usb_role_switch_put(typec->ports[i]->role_sw);
|
usb_role_switch_put(typec->ports[i]->role_sw);
|
||||||
typec_switch_put(typec->ports[i]->ori_sw);
|
typec_switch_put(typec->ports[i]->ori_sw);
|
||||||
typec_mux_put(typec->ports[i]->mux);
|
typec_mux_put(typec->ports[i]->mux);
|
||||||
|
cros_typec_unregister_port_altmodes(typec->ports[i]);
|
||||||
typec_unregister_port(typec->ports[i]->port);
|
typec_unregister_port(typec->ports[i]->port);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Fake the alt mode structs until we actually start registering Type C port
|
* Register port alt modes with known values till we start retrieving
|
||||||
* and partner alt modes.
|
* port capabilities from the EC.
|
||||||
*/
|
*/
|
||||||
static void cros_typec_register_port_altmodes(struct cros_typec_data *typec,
|
static int cros_typec_register_port_altmodes(struct cros_typec_data *typec,
|
||||||
int port_num)
|
int port_num)
|
||||||
{
|
{
|
||||||
struct cros_typec_port *port = typec->ports[port_num];
|
struct cros_typec_port *port = typec->ports[port_num];
|
||||||
|
struct typec_altmode_desc desc;
|
||||||
|
struct typec_altmode *amode;
|
||||||
|
|
||||||
/* All PD capable CrOS devices are assumed to support DP altmode. */
|
/* All PD capable CrOS devices are assumed to support DP altmode. */
|
||||||
port->port_altmode[CROS_EC_ALTMODE_DP].svid = USB_TYPEC_DP_SID;
|
desc.svid = USB_TYPEC_DP_SID,
|
||||||
port->port_altmode[CROS_EC_ALTMODE_DP].mode = USB_TYPEC_DP_MODE;
|
desc.mode = USB_TYPEC_DP_MODE,
|
||||||
|
desc.vdo = DP_PORT_VDO,
|
||||||
|
amode = typec_port_register_altmode(port->port, &desc);
|
||||||
|
if (IS_ERR(amode))
|
||||||
|
return PTR_ERR(amode);
|
||||||
|
port->port_altmode[CROS_EC_ALTMODE_DP] = amode;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Register TBT compatibility alt mode. The EC will not enter the mode
|
* Register TBT compatibility alt mode. The EC will not enter the mode
|
||||||
* if it doesn't support it, so it's safe to register it unconditionally
|
* if it doesn't support it, so it's safe to register it unconditionally
|
||||||
* here for now.
|
* here for now.
|
||||||
*/
|
*/
|
||||||
port->port_altmode[CROS_EC_ALTMODE_TBT].svid = USB_TYPEC_TBT_SID;
|
memset(&desc, 0, sizeof(desc));
|
||||||
port->port_altmode[CROS_EC_ALTMODE_TBT].mode = TYPEC_ANY_MODE;
|
desc.svid = USB_TYPEC_TBT_SID,
|
||||||
|
desc.mode = TYPEC_ANY_MODE,
|
||||||
|
amode = typec_port_register_altmode(port->port, &desc);
|
||||||
|
if (IS_ERR(amode))
|
||||||
|
return PTR_ERR(amode);
|
||||||
|
port->port_altmode[CROS_EC_ALTMODE_TBT] = amode;
|
||||||
|
|
||||||
port->state.alt = NULL;
|
port->state.alt = NULL;
|
||||||
port->state.mode = TYPEC_STATE_USB;
|
port->state.mode = TYPEC_STATE_USB;
|
||||||
port->state.data = NULL;
|
port->state.data = NULL;
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cros_typec_init_ports(struct cros_typec_data *typec)
|
static int cros_typec_init_ports(struct cros_typec_data *typec)
|
||||||
|
@ -361,7 +386,11 @@ static int cros_typec_init_ports(struct cros_typec_data *typec)
|
||||||
dev_dbg(dev, "No switch control for port %d\n",
|
dev_dbg(dev, "No switch control for port %d\n",
|
||||||
port_num);
|
port_num);
|
||||||
|
|
||||||
cros_typec_register_port_altmodes(typec, port_num);
|
ret = cros_typec_register_port_altmodes(typec, port_num);
|
||||||
|
if (ret) {
|
||||||
|
dev_err(dev, "Failed to register port altmodes\n");
|
||||||
|
goto unregister_ports;
|
||||||
|
}
|
||||||
|
|
||||||
cros_port->disc_data = devm_kzalloc(dev, EC_PROTO2_MAX_RESPONSE_SIZE, GFP_KERNEL);
|
cros_port->disc_data = devm_kzalloc(dev, EC_PROTO2_MAX_RESPONSE_SIZE, GFP_KERNEL);
|
||||||
if (!cros_port->disc_data) {
|
if (!cros_port->disc_data) {
|
||||||
|
@ -430,7 +459,7 @@ static int cros_typec_enable_tbt(struct cros_typec_data *typec,
|
||||||
data.enter_vdo |= TBT_ENTER_MODE_ACTIVE_CABLE;
|
data.enter_vdo |= TBT_ENTER_MODE_ACTIVE_CABLE;
|
||||||
|
|
||||||
if (!port->state.alt) {
|
if (!port->state.alt) {
|
||||||
port->state.alt = &port->port_altmode[CROS_EC_ALTMODE_TBT];
|
port->state.alt = port->port_altmode[CROS_EC_ALTMODE_TBT];
|
||||||
ret = cros_typec_usb_safe_state(port);
|
ret = cros_typec_usb_safe_state(port);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -472,7 +501,7 @@ static int cros_typec_enable_dp(struct cros_typec_data *typec,
|
||||||
/* Configuration VDO. */
|
/* Configuration VDO. */
|
||||||
dp_data.conf = DP_CONF_SET_PIN_ASSIGN(pd_ctrl->dp_mode);
|
dp_data.conf = DP_CONF_SET_PIN_ASSIGN(pd_ctrl->dp_mode);
|
||||||
if (!port->state.alt) {
|
if (!port->state.alt) {
|
||||||
port->state.alt = &port->port_altmode[CROS_EC_ALTMODE_DP];
|
port->state.alt = port->port_altmode[CROS_EC_ALTMODE_DP];
|
||||||
ret = cros_typec_usb_safe_state(port);
|
ret = cros_typec_usb_safe_state(port);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
Loading…
Add table
Reference in a new issue