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