1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3 * TI HD3SS3220 Type-C DRP Port Controller Driver
4 *
5 * Copyright (C) 2019 Renesas Electronics Corp.
6 */
7
8 #include <linux/module.h>
9 #include <linux/i2c.h>
10 #include <linux/usb/role.h>
11 #include <linux/irqreturn.h>
12 #include <linux/interrupt.h>
13 #include <linux/regmap.h>
14 #include <linux/slab.h>
15 #include <linux/usb/typec.h>
16 #include <linux/delay.h>
17 #include <linux/workqueue.h>
18 #include <linux/gpio/consumer.h>
19 #include <linux/regulator/consumer.h>
20 #include <linux/of_graph.h>
21
22 #define HD3SS3220_REG_CN_STAT 0x08
23 #define HD3SS3220_REG_CN_STAT_CTRL 0x09
24 #define HD3SS3220_REG_GEN_CTRL 0x0A
25 #define HD3SS3220_REG_DEV_REV 0xA0
26
27 /* Register HD3SS3220_REG_CN_STAT */
28 #define HD3SS3220_REG_CN_STAT_CURRENT_MODE_MASK (BIT(7) | BIT(6))
29 #define HD3SS3220_REG_CN_STAT_CURRENT_MODE_DEFAULT 0x00
30 #define HD3SS3220_REG_CN_STAT_CURRENT_MODE_MID BIT(6)
31 #define HD3SS3220_REG_CN_STAT_CURRENT_MODE_HIGH BIT(7)
32
33 /* Register HD3SS3220_REG_CN_STAT_CTRL*/
34 #define HD3SS3220_REG_CN_STAT_CTRL_ATTACHED_STATE_MASK (BIT(7) | BIT(6))
35 #define HD3SS3220_REG_CN_STAT_CTRL_AS_DFP BIT(6)
36 #define HD3SS3220_REG_CN_STAT_CTRL_AS_UFP BIT(7)
37 #define HD3SS3220_REG_CN_STAT_CTRL_TO_ACCESSORY (BIT(7) | BIT(6))
38 #define HD3SS3220_REG_CN_STAT_CTRL_INT_STATUS BIT(4)
39
40 /* Register HD3SS3220_REG_GEN_CTRL*/
41 #define HD3SS3220_REG_GEN_CTRL_DISABLE_TERM BIT(0)
42 #define HD3SS3220_REG_GEN_CTRL_SRC_PREF_MASK (BIT(2) | BIT(1))
43 #define HD3SS3220_REG_GEN_CTRL_SRC_PREF_DRP_DEFAULT 0x00
44 #define HD3SS3220_REG_GEN_CTRL_SRC_PREF_DRP_TRY_SNK BIT(1)
45 #define HD3SS3220_REG_GEN_CTRL_SRC_PREF_DRP_TRY_SRC (BIT(2) | BIT(1))
46 #define HD3SS3220_REG_GEN_CTRL_MODE_SELECT_MASK (BIT(5) | BIT(4))
47 #define HD3SS3220_REG_GEN_CTRL_MODE_SELECT_DEFAULT 0x00
48 #define HD3SS3220_REG_GEN_CTRL_MODE_SELECT_DFP BIT(5)
49 #define HD3SS3220_REG_GEN_CTRL_MODE_SELECT_UFP BIT(4)
50 #define HD3SS3220_REG_GEN_CTRL_MODE_SELECT_DRP (BIT(5) | BIT(4))
51
52 struct hd3ss3220 {
53 struct device *dev;
54 struct regmap *regmap;
55 struct usb_role_switch *role_sw;
56 struct typec_port *port;
57 struct delayed_work output_poll_work;
58 enum usb_role role_state;
59 bool poll;
60
61 struct gpio_desc *id_gpiod;
62 int id_irq;
63
64 struct regulator *vbus;
65 };
66
hd3ss3220_set_power_opmode(struct hd3ss3220 * hd3ss3220,int power_opmode)67 static int hd3ss3220_set_power_opmode(struct hd3ss3220 *hd3ss3220, int power_opmode)
68 {
69 int current_mode;
70
71 switch (power_opmode) {
72 case TYPEC_PWR_MODE_USB:
73 current_mode = HD3SS3220_REG_CN_STAT_CURRENT_MODE_DEFAULT;
74 break;
75 case TYPEC_PWR_MODE_1_5A:
76 current_mode = HD3SS3220_REG_CN_STAT_CURRENT_MODE_MID;
77 break;
78 case TYPEC_PWR_MODE_3_0A:
79 current_mode = HD3SS3220_REG_CN_STAT_CURRENT_MODE_HIGH;
80 break;
81 case TYPEC_PWR_MODE_PD: /* Power delivery not supported */
82 default:
83 dev_err(hd3ss3220->dev, "bad power operation mode: %d\n", power_opmode);
84 return -EINVAL;
85 }
86
87 return regmap_update_bits(hd3ss3220->regmap, HD3SS3220_REG_CN_STAT,
88 HD3SS3220_REG_CN_STAT_CURRENT_MODE_MASK,
89 current_mode);
90 }
91
hd3ss3220_set_port_type(struct hd3ss3220 * hd3ss3220,int type)92 static int hd3ss3220_set_port_type(struct hd3ss3220 *hd3ss3220, int type)
93 {
94 int mode_select, err;
95
96 switch (type) {
97 case TYPEC_PORT_SRC:
98 mode_select = HD3SS3220_REG_GEN_CTRL_MODE_SELECT_DFP;
99 break;
100 case TYPEC_PORT_SNK:
101 mode_select = HD3SS3220_REG_GEN_CTRL_MODE_SELECT_UFP;
102 break;
103 case TYPEC_PORT_DRP:
104 mode_select = HD3SS3220_REG_GEN_CTRL_MODE_SELECT_DRP;
105 break;
106 default:
107 dev_err(hd3ss3220->dev, "bad port type: %d\n", type);
108 return -EINVAL;
109 }
110
111 /* Disable termination before changing MODE_SELECT as required by datasheet */
112 err = regmap_update_bits(hd3ss3220->regmap, HD3SS3220_REG_GEN_CTRL,
113 HD3SS3220_REG_GEN_CTRL_DISABLE_TERM,
114 HD3SS3220_REG_GEN_CTRL_DISABLE_TERM);
115 if (err < 0) {
116 dev_err(hd3ss3220->dev, "Failed to disable port for mode change: %d\n", err);
117 return err;
118 }
119
120 err = regmap_update_bits(hd3ss3220->regmap, HD3SS3220_REG_GEN_CTRL,
121 HD3SS3220_REG_GEN_CTRL_MODE_SELECT_MASK,
122 mode_select);
123 if (err < 0) {
124 dev_err(hd3ss3220->dev, "Failed to change mode: %d\n", err);
125 regmap_update_bits(hd3ss3220->regmap, HD3SS3220_REG_GEN_CTRL,
126 HD3SS3220_REG_GEN_CTRL_DISABLE_TERM, 0);
127 return err;
128 }
129
130 err = regmap_update_bits(hd3ss3220->regmap, HD3SS3220_REG_GEN_CTRL,
131 HD3SS3220_REG_GEN_CTRL_DISABLE_TERM, 0);
132 if (err < 0)
133 dev_err(hd3ss3220->dev, "Failed to re-enable port after mode change: %d\n", err);
134
135 return err;
136 }
137
hd3ss3220_set_source_pref(struct hd3ss3220 * hd3ss3220,int prefer_role)138 static int hd3ss3220_set_source_pref(struct hd3ss3220 *hd3ss3220, int prefer_role)
139 {
140 int src_pref;
141
142 switch (prefer_role) {
143 case TYPEC_NO_PREFERRED_ROLE:
144 src_pref = HD3SS3220_REG_GEN_CTRL_SRC_PREF_DRP_DEFAULT;
145 break;
146 case TYPEC_SINK:
147 src_pref = HD3SS3220_REG_GEN_CTRL_SRC_PREF_DRP_TRY_SNK;
148 break;
149 case TYPEC_SOURCE:
150 src_pref = HD3SS3220_REG_GEN_CTRL_SRC_PREF_DRP_TRY_SRC;
151 break;
152 default:
153 dev_err(hd3ss3220->dev, "bad role preference: %d\n", prefer_role);
154 return -EINVAL;
155 }
156
157 return regmap_update_bits(hd3ss3220->regmap, HD3SS3220_REG_GEN_CTRL,
158 HD3SS3220_REG_GEN_CTRL_SRC_PREF_MASK,
159 src_pref);
160 }
161
hd3ss3220_get_attached_state(struct hd3ss3220 * hd3ss3220)162 static enum usb_role hd3ss3220_get_attached_state(struct hd3ss3220 *hd3ss3220)
163 {
164 unsigned int reg_val;
165 enum usb_role attached_state;
166 int ret;
167
168 ret = regmap_read(hd3ss3220->regmap, HD3SS3220_REG_CN_STAT_CTRL,
169 ®_val);
170 if (ret < 0)
171 return ret;
172
173 switch (reg_val & HD3SS3220_REG_CN_STAT_CTRL_ATTACHED_STATE_MASK) {
174 case HD3SS3220_REG_CN_STAT_CTRL_AS_DFP:
175 attached_state = USB_ROLE_HOST;
176 break;
177 case HD3SS3220_REG_CN_STAT_CTRL_AS_UFP:
178 attached_state = USB_ROLE_DEVICE;
179 break;
180 default:
181 attached_state = USB_ROLE_NONE;
182 break;
183 }
184
185 return attached_state;
186 }
187
hd3ss3220_try_role(struct typec_port * port,int role)188 static int hd3ss3220_try_role(struct typec_port *port, int role)
189 {
190 struct hd3ss3220 *hd3ss3220 = typec_get_drvdata(port);
191
192 return hd3ss3220_set_source_pref(hd3ss3220, role);
193 }
194
hd3ss3220_port_type_set(struct typec_port * port,enum typec_port_type type)195 static int hd3ss3220_port_type_set(struct typec_port *port, enum typec_port_type type)
196 {
197 struct hd3ss3220 *hd3ss3220 = typec_get_drvdata(port);
198
199 return hd3ss3220_set_port_type(hd3ss3220, type);
200 }
201
202 static const struct typec_operations hd3ss3220_ops = {
203 .try_role = hd3ss3220_try_role,
204 .port_type_set = hd3ss3220_port_type_set,
205 };
206
hd3ss3220_set_role(struct hd3ss3220 * hd3ss3220)207 static void hd3ss3220_set_role(struct hd3ss3220 *hd3ss3220)
208 {
209 enum usb_role role_state = hd3ss3220_get_attached_state(hd3ss3220);
210
211 usb_role_switch_set_role(hd3ss3220->role_sw, role_state);
212
213 switch (role_state) {
214 case USB_ROLE_HOST:
215 typec_set_data_role(hd3ss3220->port, TYPEC_HOST);
216 break;
217 case USB_ROLE_DEVICE:
218 typec_set_data_role(hd3ss3220->port, TYPEC_DEVICE);
219 break;
220 default:
221 break;
222 }
223
224 hd3ss3220->role_state = role_state;
225 }
226
output_poll_execute(struct work_struct * work)227 static void output_poll_execute(struct work_struct *work)
228 {
229 struct delayed_work *delayed_work = to_delayed_work(work);
230 struct hd3ss3220 *hd3ss3220 = container_of(delayed_work,
231 struct hd3ss3220,
232 output_poll_work);
233 enum usb_role role_state = hd3ss3220_get_attached_state(hd3ss3220);
234
235 if (hd3ss3220->role_state != role_state)
236 hd3ss3220_set_role(hd3ss3220);
237
238 schedule_delayed_work(&hd3ss3220->output_poll_work, HZ);
239 }
240
hd3ss3220_irq(struct hd3ss3220 * hd3ss3220)241 static irqreturn_t hd3ss3220_irq(struct hd3ss3220 *hd3ss3220)
242 {
243 int err;
244
245 hd3ss3220_set_role(hd3ss3220);
246 err = regmap_write_bits(hd3ss3220->regmap, HD3SS3220_REG_CN_STAT_CTRL,
247 HD3SS3220_REG_CN_STAT_CTRL_INT_STATUS,
248 HD3SS3220_REG_CN_STAT_CTRL_INT_STATUS);
249 if (err < 0)
250 return IRQ_NONE;
251
252 return IRQ_HANDLED;
253 }
254
hd3ss3220_irq_handler(int irq,void * data)255 static irqreturn_t hd3ss3220_irq_handler(int irq, void *data)
256 {
257 struct i2c_client *client = to_i2c_client(data);
258 struct hd3ss3220 *hd3ss3220 = i2c_get_clientdata(client);
259
260 return hd3ss3220_irq(hd3ss3220);
261 }
262
hd3ss3220_configure_power_opmode(struct hd3ss3220 * hd3ss3220,struct fwnode_handle * connector)263 static int hd3ss3220_configure_power_opmode(struct hd3ss3220 *hd3ss3220,
264 struct fwnode_handle *connector)
265 {
266 /*
267 * Supported power operation mode can be configured through device tree
268 */
269 const char *cap_str;
270 int ret, power_opmode;
271
272 ret = fwnode_property_read_string(connector, "typec-power-opmode", &cap_str);
273 if (ret)
274 return 0;
275
276 power_opmode = typec_find_pwr_opmode(cap_str);
277 return hd3ss3220_set_power_opmode(hd3ss3220, power_opmode);
278 }
279
hd3ss3220_configure_port_type(struct hd3ss3220 * hd3ss3220,struct fwnode_handle * connector,struct typec_capability * cap)280 static int hd3ss3220_configure_port_type(struct hd3ss3220 *hd3ss3220,
281 struct fwnode_handle *connector,
282 struct typec_capability *cap)
283 {
284 /*
285 * Port type can be configured through device tree
286 */
287 const char *cap_str;
288 int ret;
289
290 ret = fwnode_property_read_string(connector, "power-role", &cap_str);
291 if (ret)
292 return 0;
293
294 ret = typec_find_port_power_role(cap_str);
295 if (ret < 0)
296 return ret;
297
298 cap->type = ret;
299 return hd3ss3220_set_port_type(hd3ss3220, cap->type);
300 }
301
hd3ss3220_configure_source_pref(struct hd3ss3220 * hd3ss3220,struct fwnode_handle * connector,struct typec_capability * cap)302 static int hd3ss3220_configure_source_pref(struct hd3ss3220 *hd3ss3220,
303 struct fwnode_handle *connector,
304 struct typec_capability *cap)
305 {
306 /*
307 * Preferred role can be configured through device tree
308 */
309 const char *cap_str;
310 int ret;
311
312 ret = fwnode_property_read_string(connector, "try-power-role", &cap_str);
313 if (ret)
314 return 0;
315
316 ret = typec_find_power_role(cap_str);
317 if (ret < 0)
318 return ret;
319
320 cap->prefer_role = ret;
321 return hd3ss3220_set_source_pref(hd3ss3220, cap->prefer_role);
322 }
323
324 static const struct regmap_config config = {
325 .reg_bits = 8,
326 .val_bits = 8,
327 .max_register = 0x0A,
328 };
329
hd3ss3220_id_isr(int irq,void * dev_id)330 static irqreturn_t hd3ss3220_id_isr(int irq, void *dev_id)
331 {
332 struct hd3ss3220 *hd3ss3220 = dev_id;
333 int ret;
334 int id;
335
336 id = gpiod_get_value_cansleep(hd3ss3220->id_gpiod);
337 if (!id)
338 ret = regulator_enable(hd3ss3220->vbus);
339 else
340 ret = regulator_disable(hd3ss3220->vbus);
341
342 if (ret)
343 dev_err(hd3ss3220->dev,
344 "vbus regulator %s failed: %d\n", id ? "disable" : "enable", ret);
345
346 return IRQ_HANDLED;
347 }
348
hd3ss3220_probe(struct i2c_client * client)349 static int hd3ss3220_probe(struct i2c_client *client)
350 {
351 struct typec_capability typec_cap = { };
352 struct fwnode_handle *connector, *ep;
353 struct hd3ss3220 *hd3ss3220;
354 struct regulator *vbus;
355 unsigned int data;
356 int ret;
357
358 hd3ss3220 = devm_kzalloc(&client->dev, sizeof(struct hd3ss3220),
359 GFP_KERNEL);
360 if (!hd3ss3220)
361 return -ENOMEM;
362
363 i2c_set_clientdata(client, hd3ss3220);
364
365 hd3ss3220->dev = &client->dev;
366 hd3ss3220->regmap = devm_regmap_init_i2c(client, &config);
367 if (IS_ERR(hd3ss3220->regmap))
368 return PTR_ERR(hd3ss3220->regmap);
369
370 /* For backward compatibility check the connector child node first */
371 connector = device_get_named_child_node(hd3ss3220->dev, "connector");
372 if (connector) {
373 hd3ss3220->role_sw = fwnode_usb_role_switch_get(connector);
374 } else {
375 ep = fwnode_graph_get_next_endpoint(dev_fwnode(hd3ss3220->dev), NULL);
376 if (!ep)
377 return -ENODEV;
378 connector = fwnode_graph_get_remote_port_parent(ep);
379 fwnode_handle_put(ep);
380 if (!connector)
381 return -ENODEV;
382 hd3ss3220->role_sw = usb_role_switch_get(hd3ss3220->dev);
383 }
384
385 if (IS_ERR(hd3ss3220->role_sw)) {
386 ret = PTR_ERR(hd3ss3220->role_sw);
387 goto err_put_fwnode;
388 }
389
390 vbus = devm_of_regulator_get_optional(hd3ss3220->dev,
391 to_of_node(connector),
392 "vbus");
393 if (IS_ERR(vbus) && vbus != ERR_PTR(-ENODEV)) {
394 ret = PTR_ERR(vbus);
395 dev_err(hd3ss3220->dev, "failed to get vbus: %d", ret);
396 goto err_put_fwnode;
397 }
398
399 hd3ss3220->vbus = (vbus == ERR_PTR(-ENODEV) ? NULL : vbus);
400
401 if (hd3ss3220->vbus) {
402 hd3ss3220->id_gpiod = devm_gpiod_get_optional(hd3ss3220->dev,
403 "id",
404 GPIOD_IN);
405 if (IS_ERR(hd3ss3220->id_gpiod)) {
406 ret = PTR_ERR(hd3ss3220->id_gpiod);
407 goto err_put_fwnode;
408 }
409 }
410
411 if (hd3ss3220->id_gpiod) {
412 hd3ss3220->id_irq = gpiod_to_irq(hd3ss3220->id_gpiod);
413 if (hd3ss3220->id_irq < 0) {
414 ret = hd3ss3220->id_irq;
415 dev_err(hd3ss3220->dev,
416 "failed to get ID gpio: %d\n",
417 hd3ss3220->id_irq);
418 goto err_put_fwnode;
419 }
420
421 ret = devm_request_threaded_irq(hd3ss3220->dev,
422 hd3ss3220->id_irq, NULL,
423 hd3ss3220_id_isr,
424 IRQF_TRIGGER_RISING |
425 IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
426 dev_name(hd3ss3220->dev), hd3ss3220);
427 if (ret < 0) {
428 dev_err(hd3ss3220->dev, "failed to get ID irq: %d\n", ret);
429 goto err_put_fwnode;
430 }
431 }
432
433 typec_cap.prefer_role = TYPEC_NO_PREFERRED_ROLE;
434 typec_cap.driver_data = hd3ss3220;
435 typec_cap.type = TYPEC_PORT_DRP;
436 typec_cap.data = TYPEC_PORT_DRD;
437 typec_cap.ops = &hd3ss3220_ops;
438 typec_cap.fwnode = connector;
439
440 ret = hd3ss3220_configure_source_pref(hd3ss3220, connector, &typec_cap);
441 if (ret < 0)
442 goto err_put_role;
443
444 ret = hd3ss3220_configure_port_type(hd3ss3220, connector, &typec_cap);
445 if (ret < 0)
446 goto err_put_role;
447
448 hd3ss3220->port = typec_register_port(&client->dev, &typec_cap);
449 if (IS_ERR(hd3ss3220->port)) {
450 ret = PTR_ERR(hd3ss3220->port);
451 goto err_put_role;
452 }
453
454 ret = hd3ss3220_configure_power_opmode(hd3ss3220, connector);
455 if (ret < 0)
456 goto err_unreg_port;
457
458 hd3ss3220_set_role(hd3ss3220);
459 ret = regmap_read(hd3ss3220->regmap, HD3SS3220_REG_CN_STAT_CTRL, &data);
460 if (ret < 0)
461 goto err_unreg_port;
462
463 if (data & HD3SS3220_REG_CN_STAT_CTRL_INT_STATUS) {
464 ret = regmap_write(hd3ss3220->regmap,
465 HD3SS3220_REG_CN_STAT_CTRL,
466 data | HD3SS3220_REG_CN_STAT_CTRL_INT_STATUS);
467 if (ret < 0)
468 goto err_unreg_port;
469 }
470
471 if (client->irq > 0) {
472 ret = devm_request_threaded_irq(&client->dev, client->irq, NULL,
473 hd3ss3220_irq_handler,
474 IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
475 "hd3ss3220", &client->dev);
476 if (ret)
477 goto err_unreg_port;
478 } else {
479 INIT_DELAYED_WORK(&hd3ss3220->output_poll_work, output_poll_execute);
480 hd3ss3220->poll = true;
481 }
482
483 ret = i2c_smbus_read_byte_data(client, HD3SS3220_REG_DEV_REV);
484 if (ret < 0)
485 goto err_unreg_port;
486
487 fwnode_handle_put(connector);
488
489 if (hd3ss3220->poll)
490 schedule_delayed_work(&hd3ss3220->output_poll_work, HZ);
491
492 dev_info(&client->dev, "probed revision=0x%x\n", ret);
493
494 return 0;
495 err_unreg_port:
496 typec_unregister_port(hd3ss3220->port);
497 err_put_role:
498 usb_role_switch_put(hd3ss3220->role_sw);
499 err_put_fwnode:
500 fwnode_handle_put(connector);
501
502 return ret;
503 }
504
hd3ss3220_remove(struct i2c_client * client)505 static void hd3ss3220_remove(struct i2c_client *client)
506 {
507 struct hd3ss3220 *hd3ss3220 = i2c_get_clientdata(client);
508
509 if (hd3ss3220->poll)
510 cancel_delayed_work_sync(&hd3ss3220->output_poll_work);
511
512 typec_unregister_port(hd3ss3220->port);
513 usb_role_switch_put(hd3ss3220->role_sw);
514 }
515
516 static const struct of_device_id dev_ids[] = {
517 { .compatible = "ti,hd3ss3220"},
518 {}
519 };
520 MODULE_DEVICE_TABLE(of, dev_ids);
521
522 static struct i2c_driver hd3ss3220_driver = {
523 .driver = {
524 .name = "hd3ss3220",
525 .of_match_table = dev_ids,
526 },
527 .probe = hd3ss3220_probe,
528 .remove = hd3ss3220_remove,
529 };
530
531 module_i2c_driver(hd3ss3220_driver);
532
533 MODULE_AUTHOR("Biju Das <biju.das@bp.renesas.com>");
534 MODULE_DESCRIPTION("TI HD3SS3220 DRP Port Controller Driver");
535 MODULE_LICENSE("GPL");
536