@@ -1624,11 +1624,71 @@ static struct fwnode_handle *ucsi_find_fwnode(struct ucsi_connector *con)
16241624 return NULL ;
16251625}
16261626
1627+ static void ucsi_init_port (struct ucsi * ucsi , struct ucsi_connector * con )
1628+ {
1629+ enum usb_role u_role = USB_ROLE_NONE ;
1630+ int ret ;
1631+
1632+ /* Get the status */
1633+ ret = ucsi_get_connector_status (con , false);
1634+ if (ret ) {
1635+ dev_err (ucsi -> dev , "con%d: failed to get status\n" , con -> num );
1636+ return ;
1637+ }
1638+
1639+ if (ucsi -> ops -> connector_status )
1640+ ucsi -> ops -> connector_status (con );
1641+
1642+ switch (UCSI_CONSTAT (con , PARTNER_TYPE )) {
1643+ case UCSI_CONSTAT_PARTNER_TYPE_UFP :
1644+ case UCSI_CONSTAT_PARTNER_TYPE_CABLE_AND_UFP :
1645+ u_role = USB_ROLE_HOST ;
1646+ fallthrough ;
1647+ case UCSI_CONSTAT_PARTNER_TYPE_CABLE :
1648+ typec_set_data_role (con -> port , TYPEC_HOST );
1649+ break ;
1650+ case UCSI_CONSTAT_PARTNER_TYPE_DFP :
1651+ u_role = USB_ROLE_DEVICE ;
1652+ typec_set_data_role (con -> port , TYPEC_DEVICE );
1653+ break ;
1654+ default :
1655+ break ;
1656+ }
1657+
1658+ /* Check if there is already something connected */
1659+ if (UCSI_CONSTAT (con , CONNECTED )) {
1660+ typec_set_pwr_role (con -> port , UCSI_CONSTAT (con , PWR_DIR ));
1661+ ucsi_register_partner (con );
1662+ ucsi_pwr_opmode_change (con );
1663+ ucsi_orientation (con );
1664+ ucsi_port_psy_changed (con );
1665+ if (con -> ucsi -> cap .features & UCSI_CAP_GET_PD_MESSAGE )
1666+ ucsi_get_partner_identity (con );
1667+ if (con -> ucsi -> cap .features & UCSI_CAP_CABLE_DETAILS )
1668+ ucsi_check_cable (con );
1669+ }
1670+
1671+ /* Only notify USB controller if partner supports USB data */
1672+ if (!(UCSI_CONSTAT (con , PARTNER_FLAG_USB )))
1673+ u_role = USB_ROLE_NONE ;
1674+
1675+ ret = usb_role_switch_set_role (con -> usb_role_sw , u_role );
1676+ if (ret )
1677+ dev_err (ucsi -> dev , "con:%d: failed to set usb role:%d\n" ,
1678+ con -> num , u_role );
1679+
1680+ if (con -> partner && UCSI_CONSTAT (con , PWR_OPMODE ) == UCSI_CONSTAT_PWR_OPMODE_PD ) {
1681+ ucsi_register_device_pdos (con );
1682+ ucsi_get_src_pdos (con );
1683+ ucsi_check_altmodes (con );
1684+ ucsi_check_connector_capability (con );
1685+ }
1686+ }
1687+
16271688static int ucsi_register_port (struct ucsi * ucsi , struct ucsi_connector * con )
16281689{
16291690 struct typec_capability * cap = & con -> typec_cap ;
16301691 enum typec_accessory * accessory = cap -> accessory ;
1631- enum usb_role u_role = USB_ROLE_NONE ;
16321692 u64 command ;
16331693 char * name ;
16341694 int ret ;
@@ -1729,63 +1789,6 @@ static int ucsi_register_port(struct ucsi *ucsi, struct ucsi_connector *con)
17291789 goto out ;
17301790 }
17311791
1732- /* Get the status */
1733- ret = ucsi_get_connector_status (con , false);
1734- if (ret ) {
1735- dev_err (ucsi -> dev , "con%d: failed to get status\n" , con -> num );
1736- goto out ;
1737- }
1738-
1739- if (ucsi -> ops -> connector_status )
1740- ucsi -> ops -> connector_status (con );
1741-
1742- switch (UCSI_CONSTAT (con , PARTNER_TYPE )) {
1743- case UCSI_CONSTAT_PARTNER_TYPE_UFP :
1744- case UCSI_CONSTAT_PARTNER_TYPE_CABLE_AND_UFP :
1745- u_role = USB_ROLE_HOST ;
1746- fallthrough ;
1747- case UCSI_CONSTAT_PARTNER_TYPE_CABLE :
1748- typec_set_data_role (con -> port , TYPEC_HOST );
1749- break ;
1750- case UCSI_CONSTAT_PARTNER_TYPE_DFP :
1751- u_role = USB_ROLE_DEVICE ;
1752- typec_set_data_role (con -> port , TYPEC_DEVICE );
1753- break ;
1754- default :
1755- break ;
1756- }
1757-
1758- /* Check if there is already something connected */
1759- if (UCSI_CONSTAT (con , CONNECTED )) {
1760- typec_set_pwr_role (con -> port , UCSI_CONSTAT (con , PWR_DIR ));
1761- ucsi_register_partner (con );
1762- ucsi_pwr_opmode_change (con );
1763- ucsi_orientation (con );
1764- ucsi_port_psy_changed (con );
1765- if (con -> ucsi -> cap .features & UCSI_CAP_GET_PD_MESSAGE )
1766- ucsi_get_partner_identity (con );
1767- if (con -> ucsi -> cap .features & UCSI_CAP_CABLE_DETAILS )
1768- ucsi_check_cable (con );
1769- }
1770-
1771- /* Only notify USB controller if partner supports USB data */
1772- if (!(UCSI_CONSTAT (con , PARTNER_FLAG_USB )))
1773- u_role = USB_ROLE_NONE ;
1774-
1775- ret = usb_role_switch_set_role (con -> usb_role_sw , u_role );
1776- if (ret ) {
1777- dev_err (ucsi -> dev , "con:%d: failed to set usb role:%d\n" ,
1778- con -> num , u_role );
1779- ret = 0 ;
1780- }
1781-
1782- if (con -> partner && UCSI_CONSTAT (con , PWR_OPMODE ) == UCSI_CONSTAT_PWR_OPMODE_PD ) {
1783- ucsi_register_device_pdos (con );
1784- ucsi_get_src_pdos (con );
1785- ucsi_check_altmodes (con );
1786- ucsi_check_connector_capability (con );
1787- }
1788-
17891792 trace_ucsi_register_port (con -> num , con );
17901793
17911794out :
@@ -1903,17 +1906,29 @@ static int ucsi_init(struct ucsi *ucsi)
19031906 goto err_unregister ;
19041907 }
19051908
1909+ /* Delay other interactions with each connector until ucsi_init_port is done */
1910+ for (i = 0 ; i < ucsi -> cap .num_connectors ; i ++ )
1911+ mutex_lock (& connector [i ].lock );
1912+
19061913 /* Enable all supported notifications */
19071914 ntfy = ucsi_get_supported_notifications (ucsi );
19081915 command = UCSI_SET_NOTIFICATION_ENABLE | ntfy ;
19091916 ucsi -> message_in_size = 0 ;
19101917 ret = ucsi_send_command (ucsi , command );
1911- if (ret < 0 )
1918+ if (ret < 0 ) {
1919+ for (i = 0 ; i < ucsi -> cap .num_connectors ; i ++ )
1920+ mutex_unlock (& connector [i ].lock );
19121921 goto err_unregister ;
1922+ }
19131923
19141924 ucsi -> connector = connector ;
19151925 ucsi -> ntfy = ntfy ;
19161926
1927+ for (i = 0 ; i < ucsi -> cap .num_connectors ; i ++ ) {
1928+ ucsi_init_port (ucsi , & connector [i ]);
1929+ mutex_unlock (& connector [i ].lock );
1930+ }
1931+
19171932 mutex_lock (& ucsi -> ppm_lock );
19181933 ret = ucsi -> ops -> read_cci (ucsi , & cci );
19191934 mutex_unlock (& ucsi -> ppm_lock );
0 commit comments