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