1111#include <linux/of.h>
1212#include <linux/platform_data/cros_ec_commands.h>
1313#include <linux/platform_data/cros_ec_proto.h>
14+ #include <linux/platform_data/cros_usbpd_notify.h>
1415#include <linux/platform_device.h>
1516#include <linux/usb/typec.h>
1617
1718#define DRV_NAME "cros-ec-typec"
1819
20+ /* Per port data. */
21+ struct cros_typec_port {
22+ struct typec_port * port ;
23+ /* Initial capabilities for the port. */
24+ struct typec_capability caps ;
25+ struct typec_partner * partner ;
26+ /* Port partner PD identity info. */
27+ struct usb_pd_identity p_identity ;
28+ };
29+
1930/* Platform-specific data for the Chrome OS EC Type C controller. */
2031struct cros_typec_data {
2132 struct device * dev ;
2233 struct cros_ec_device * ec ;
2334 int num_ports ;
2435 unsigned int cmd_ver ;
2536 /* Array of ports, indexed by port number. */
26- struct typec_port * ports [EC_USB_PD_MAX_PORTS ];
27- /* Initial capabilities for each port. */
28- struct typec_capability * caps [EC_USB_PD_MAX_PORTS ];
37+ struct cros_typec_port * ports [EC_USB_PD_MAX_PORTS ];
38+ struct notifier_block nb ;
2939};
3040
3141static int cros_typec_parse_port_props (struct typec_capability * cap ,
@@ -74,14 +84,25 @@ static int cros_typec_parse_port_props(struct typec_capability *cap,
7484 return 0 ;
7585}
7686
87+ static void cros_unregister_ports (struct cros_typec_data * typec )
88+ {
89+ int i ;
90+
91+ for (i = 0 ; i < typec -> num_ports ; i ++ ) {
92+ if (!typec -> ports [i ])
93+ continue ;
94+ typec_unregister_port (typec -> ports [i ]-> port );
95+ }
96+ }
97+
7798static int cros_typec_init_ports (struct cros_typec_data * typec )
7899{
79100 struct device * dev = typec -> dev ;
80101 struct typec_capability * cap ;
81102 struct fwnode_handle * fwnode ;
103+ struct cros_typec_port * cros_port ;
82104 const char * port_prop ;
83105 int ret ;
84- int i ;
85106 int nports ;
86107 u32 port_num = 0 ;
87108
@@ -113,31 +134,31 @@ static int cros_typec_init_ports(struct cros_typec_data *typec)
113134
114135 dev_dbg (dev , "Registering port %d\n" , port_num );
115136
116- cap = devm_kzalloc (dev , sizeof (* cap ), GFP_KERNEL );
117- if (!cap ) {
137+ cros_port = devm_kzalloc (dev , sizeof (* cros_port ), GFP_KERNEL );
138+ if (!cros_port ) {
118139 ret = - ENOMEM ;
119140 goto unregister_ports ;
120141 }
121142
122- typec -> caps [port_num ] = cap ;
143+ typec -> ports [port_num ] = cros_port ;
144+ cap = & cros_port -> caps ;
123145
124146 ret = cros_typec_parse_port_props (cap , fwnode , dev );
125147 if (ret < 0 )
126148 goto unregister_ports ;
127149
128- typec -> ports [ port_num ] = typec_register_port (dev , cap );
129- if (IS_ERR (typec -> ports [ port_num ] )) {
150+ cros_port -> port = typec_register_port (dev , cap );
151+ if (IS_ERR (cros_port -> port )) {
130152 dev_err (dev , "Failed to register port %d\n" , port_num );
131- ret = PTR_ERR (typec -> ports [ port_num ] );
153+ ret = PTR_ERR (cros_port -> port );
132154 goto unregister_ports ;
133155 }
134156 }
135157
136158 return 0 ;
137159
138160unregister_ports :
139- for (i = 0 ; i < typec -> num_ports ; i ++ )
140- typec_unregister_port (typec -> ports [i ]);
161+ cros_unregister_ports (typec );
141162 return ret ;
142163}
143164
@@ -172,10 +193,34 @@ static int cros_typec_ec_command(struct cros_typec_data *typec,
172193 return ret ;
173194}
174195
196+ static int cros_typec_add_partner (struct cros_typec_data * typec , int port_num ,
197+ bool pd_en )
198+ {
199+ struct cros_typec_port * port = typec -> ports [port_num ];
200+ struct typec_partner_desc p_desc = {
201+ .usb_pd = pd_en ,
202+ };
203+ int ret = 0 ;
204+
205+ /*
206+ * Fill an initial PD identity, which will then be updated with info
207+ * from the EC.
208+ */
209+ p_desc .identity = & port -> p_identity ;
210+
211+ port -> partner = typec_register_partner (port -> port , & p_desc );
212+ if (IS_ERR (port -> partner )) {
213+ ret = PTR_ERR (port -> partner );
214+ port -> partner = NULL ;
215+ }
216+
217+ return ret ;
218+ }
219+
175220static void cros_typec_set_port_params_v0 (struct cros_typec_data * typec ,
176221 int port_num , struct ec_response_usb_pd_control * resp )
177222{
178- struct typec_port * port = typec -> ports [port_num ];
223+ struct typec_port * port = typec -> ports [port_num ]-> port ;
179224 enum typec_orientation polarity ;
180225
181226 if (!resp -> enabled )
@@ -192,8 +237,10 @@ static void cros_typec_set_port_params_v0(struct cros_typec_data *typec,
192237static void cros_typec_set_port_params_v1 (struct cros_typec_data * typec ,
193238 int port_num , struct ec_response_usb_pd_control_v1 * resp )
194239{
195- struct typec_port * port = typec -> ports [port_num ];
240+ struct typec_port * port = typec -> ports [port_num ]-> port ;
196241 enum typec_orientation polarity ;
242+ bool pd_en ;
243+ int ret ;
197244
198245 if (!(resp -> enabled & PD_CTRL_RESP_ENABLED_CONNECTED ))
199246 polarity = TYPEC_ORIENTATION_NONE ;
@@ -208,6 +255,25 @@ static void cros_typec_set_port_params_v1(struct cros_typec_data *typec,
208255 TYPEC_SOURCE : TYPEC_SINK );
209256 typec_set_vconn_role (port , resp -> role & PD_CTRL_RESP_ROLE_VCONN ?
210257 TYPEC_SOURCE : TYPEC_SINK );
258+
259+ /* Register/remove partners when a connect/disconnect occurs. */
260+ if (resp -> enabled & PD_CTRL_RESP_ENABLED_CONNECTED ) {
261+ if (typec -> ports [port_num ]-> partner )
262+ return ;
263+
264+ pd_en = resp -> enabled & PD_CTRL_RESP_ENABLED_PD_CAPABLE ;
265+ ret = cros_typec_add_partner (typec , port_num , pd_en );
266+ if (ret )
267+ dev_warn (typec -> dev ,
268+ "Failed to register partner on port: %d\n" ,
269+ port_num );
270+ } else {
271+ if (!typec -> ports [port_num ]-> partner )
272+ return ;
273+
274+ typec_unregister_partner (typec -> ports [port_num ]-> partner );
275+ typec -> ports [port_num ]-> partner = NULL ;
276+ }
211277}
212278
213279static int cros_typec_port_update (struct cros_typec_data * typec , int port_num )
@@ -272,6 +338,22 @@ static int cros_typec_get_cmd_version(struct cros_typec_data *typec)
272338 return 0 ;
273339}
274340
341+ static int cros_ec_typec_event (struct notifier_block * nb ,
342+ unsigned long host_event , void * _notify )
343+ {
344+ struct cros_typec_data * typec = container_of (nb , struct cros_typec_data ,
345+ nb );
346+ int ret , i ;
347+
348+ for (i = 0 ; i < typec -> num_ports ; i ++ ) {
349+ ret = cros_typec_port_update (typec , i );
350+ if (ret < 0 )
351+ dev_warn (typec -> dev , "Update failed for port: %d\n" , i );
352+ }
353+
354+ return NOTIFY_OK ;
355+ }
356+
275357#ifdef CONFIG_ACPI
276358static const struct acpi_device_id cros_typec_acpi_id [] = {
277359 { "GOOG0014" , 0 },
@@ -332,12 +414,15 @@ static int cros_typec_probe(struct platform_device *pdev)
332414 goto unregister_ports ;
333415 }
334416
417+ typec -> nb .notifier_call = cros_ec_typec_event ;
418+ ret = cros_usbpd_register_notify (& typec -> nb );
419+ if (ret < 0 )
420+ goto unregister_ports ;
421+
335422 return 0 ;
336423
337424unregister_ports :
338- for (i = 0 ; i < typec -> num_ports ; i ++ )
339- if (typec -> ports [i ])
340- typec_unregister_port (typec -> ports [i ]);
425+ cros_unregister_ports (typec );
341426 return ret ;
342427}
343428
0 commit comments