xref: /linux/drivers/usb/typec/wusb3801.c (revision cdd5b5a9761fd66d17586e4f4ba6588c70e640ea)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Willsemi WUSB3801 Type-C port controller driver
4  *
5  * Copyright (C) 2022 Samuel Holland <samuel@sholland.org>
6  */
7 
8 #include <linux/i2c.h>
9 #include <linux/module.h>
10 #include <linux/regmap.h>
11 #include <linux/regulator/consumer.h>
12 #include <linux/usb/typec.h>
13 
14 #define WUSB3801_REG_DEVICE_ID		0x01
15 #define WUSB3801_REG_CTRL0		0x02
16 #define WUSB3801_REG_INT		0x03
17 #define WUSB3801_REG_STAT		0x04
18 #define WUSB3801_REG_CTRL1		0x05
19 #define WUSB3801_REG_TEST00		0x06
20 #define WUSB3801_REG_TEST01		0x07
21 #define WUSB3801_REG_TEST02		0x08
22 #define WUSB3801_REG_TEST03		0x09
23 #define WUSB3801_REG_TEST04		0x0a
24 #define WUSB3801_REG_TEST05		0x0b
25 #define WUSB3801_REG_TEST06		0x0c
26 #define WUSB3801_REG_TEST07		0x0d
27 #define WUSB3801_REG_TEST08		0x0e
28 #define WUSB3801_REG_TEST09		0x0f
29 #define WUSB3801_REG_TEST0A		0x10
30 #define WUSB3801_REG_TEST0B		0x11
31 #define WUSB3801_REG_TEST0C		0x12
32 #define WUSB3801_REG_TEST0D		0x13
33 #define WUSB3801_REG_TEST0E		0x14
34 #define WUSB3801_REG_TEST0F		0x15
35 #define WUSB3801_REG_TEST10		0x16
36 #define WUSB3801_REG_TEST11		0x17
37 #define WUSB3801_REG_TEST12		0x18
38 
39 #define WUSB3801_DEVICE_ID_VERSION_ID	GENMASK(7, 3)
40 #define WUSB3801_DEVICE_ID_VENDOR_ID	GENMASK(2, 0)
41 
42 #define WUSB3801_CTRL0_DIS_ACC_SUPPORT	BIT(7)
43 #define WUSB3801_CTRL0_TRY		GENMASK(6, 5)
44 #define WUSB3801_CTRL0_TRY_NONE		(0x0 << 5)
45 #define WUSB3801_CTRL0_TRY_SNK		(0x1 << 5)
46 #define WUSB3801_CTRL0_TRY_SRC		(0x2 << 5)
47 #define WUSB3801_CTRL0_CURRENT		GENMASK(4, 3) /* SRC */
48 #define WUSB3801_CTRL0_CURRENT_DEFAULT	(0x0 << 3)
49 #define WUSB3801_CTRL0_CURRENT_1_5A	(0x1 << 3)
50 #define WUSB3801_CTRL0_CURRENT_3_0A	(0x2 << 3)
51 #define WUSB3801_CTRL0_ROLE		GENMASK(2, 1)
52 #define WUSB3801_CTRL0_ROLE_SNK		(0x0 << 1)
53 #define WUSB3801_CTRL0_ROLE_SRC		(0x1 << 1)
54 #define WUSB3801_CTRL0_ROLE_DRP		(0x2 << 1)
55 #define WUSB3801_CTRL0_INT_MASK		BIT(0)
56 
57 #define WUSB3801_INT_ATTACHED		BIT(0)
58 #define WUSB3801_INT_DETACHED		BIT(1)
59 
60 #define WUSB3801_STAT_VBUS_DETECTED	BIT(7)
61 #define WUSB3801_STAT_CURRENT		GENMASK(6, 5) /* SNK */
62 #define WUSB3801_STAT_CURRENT_STANDBY	(0x0 << 5)
63 #define WUSB3801_STAT_CURRENT_DEFAULT	(0x1 << 5)
64 #define WUSB3801_STAT_CURRENT_1_5A	(0x2 << 5)
65 #define WUSB3801_STAT_CURRENT_3_0A	(0x3 << 5)
66 #define WUSB3801_STAT_PARTNER		GENMASK(4, 2)
67 #define WUSB3801_STAT_PARTNER_STANDBY	(0x0 << 2)
68 #define WUSB3801_STAT_PARTNER_SNK	(0x1 << 2)
69 #define WUSB3801_STAT_PARTNER_SRC	(0x2 << 2)
70 #define WUSB3801_STAT_PARTNER_AUDIO	(0x3 << 2)
71 #define WUSB3801_STAT_PARTNER_DEBUG	(0x4 << 2)
72 #define WUSB3801_STAT_ORIENTATION	GENMASK(1, 0)
73 #define WUSB3801_STAT_ORIENTATION_NONE	(0x0 << 0)
74 #define WUSB3801_STAT_ORIENTATION_CC1	(0x1 << 0)
75 #define WUSB3801_STAT_ORIENTATION_CC2	(0x2 << 0)
76 #define WUSB3801_STAT_ORIENTATION_BOTH	(0x3 << 0)
77 
78 #define WUSB3801_CTRL1_SM_RESET		BIT(0)
79 
80 #define WUSB3801_TEST01_VENDOR_SUB_ID	(BIT(8) | BIT(6))
81 
82 #define WUSB3801_TEST02_FORCE_ERR_RCY	BIT(8)
83 
84 #define WUSB3801_TEST0A_WAIT_VBUS	BIT(5)
85 
86 struct wusb3801 {
87 	struct typec_capability	cap;
88 	struct device		*dev;
89 	struct typec_partner	*partner;
90 	struct typec_port	*port;
91 	struct regmap		*regmap;
92 	struct regulator	*vbus_supply;
93 	unsigned int		partner_type;
94 	enum typec_port_type	port_type;
95 	enum typec_pwr_opmode	pwr_opmode;
96 	bool			vbus_on;
97 };
98 
wusb3801_get_default_role(struct wusb3801 * wusb3801)99 static enum typec_role wusb3801_get_default_role(struct wusb3801 *wusb3801)
100 {
101 	switch (wusb3801->port_type) {
102 	case TYPEC_PORT_SRC:
103 		return TYPEC_SOURCE;
104 	case TYPEC_PORT_SNK:
105 		return TYPEC_SINK;
106 	case TYPEC_PORT_DRP:
107 	default:
108 		if (wusb3801->cap.prefer_role == TYPEC_SOURCE)
109 			return TYPEC_SOURCE;
110 		return TYPEC_SINK;
111 	}
112 }
113 
wusb3801_map_port_type(enum typec_port_type type)114 static int wusb3801_map_port_type(enum typec_port_type type)
115 {
116 	switch (type) {
117 	case TYPEC_PORT_SRC:
118 		return WUSB3801_CTRL0_ROLE_SRC;
119 	case TYPEC_PORT_SNK:
120 		return WUSB3801_CTRL0_ROLE_SNK;
121 	case TYPEC_PORT_DRP:
122 	default:
123 		return WUSB3801_CTRL0_ROLE_DRP;
124 	}
125 }
126 
wusb3801_map_pwr_opmode(enum typec_pwr_opmode mode)127 static int wusb3801_map_pwr_opmode(enum typec_pwr_opmode mode)
128 {
129 	switch (mode) {
130 	case TYPEC_PWR_MODE_USB:
131 	default:
132 		return WUSB3801_CTRL0_CURRENT_DEFAULT;
133 	case TYPEC_PWR_MODE_1_5A:
134 		return WUSB3801_CTRL0_CURRENT_1_5A;
135 	case TYPEC_PWR_MODE_3_0A:
136 		return WUSB3801_CTRL0_CURRENT_3_0A;
137 	}
138 }
139 
wusb3801_map_try_role(int role)140 static unsigned int wusb3801_map_try_role(int role)
141 {
142 	switch (role) {
143 	case TYPEC_NO_PREFERRED_ROLE:
144 	default:
145 		return WUSB3801_CTRL0_TRY_NONE;
146 	case TYPEC_SINK:
147 		return WUSB3801_CTRL0_TRY_SNK;
148 	case TYPEC_SOURCE:
149 		return WUSB3801_CTRL0_TRY_SRC;
150 	}
151 }
152 
wusb3801_unmap_orientation(unsigned int status)153 static enum typec_orientation wusb3801_unmap_orientation(unsigned int status)
154 {
155 	switch (status & WUSB3801_STAT_ORIENTATION) {
156 	case WUSB3801_STAT_ORIENTATION_NONE:
157 	case WUSB3801_STAT_ORIENTATION_BOTH:
158 	default:
159 		return TYPEC_ORIENTATION_NONE;
160 	case WUSB3801_STAT_ORIENTATION_CC1:
161 		return TYPEC_ORIENTATION_NORMAL;
162 	case WUSB3801_STAT_ORIENTATION_CC2:
163 		return TYPEC_ORIENTATION_REVERSE;
164 	}
165 }
166 
wusb3801_unmap_pwr_opmode(unsigned int status)167 static enum typec_pwr_opmode wusb3801_unmap_pwr_opmode(unsigned int status)
168 {
169 	switch (status & WUSB3801_STAT_CURRENT) {
170 	case WUSB3801_STAT_CURRENT_STANDBY:
171 	case WUSB3801_STAT_CURRENT_DEFAULT:
172 	default:
173 		return TYPEC_PWR_MODE_USB;
174 	case WUSB3801_STAT_CURRENT_1_5A:
175 		return TYPEC_PWR_MODE_1_5A;
176 	case WUSB3801_STAT_CURRENT_3_0A:
177 		return TYPEC_PWR_MODE_3_0A;
178 	}
179 }
180 
wusb3801_try_role(struct typec_port * port,int role)181 static int wusb3801_try_role(struct typec_port *port, int role)
182 {
183 	struct wusb3801 *wusb3801 = typec_get_drvdata(port);
184 
185 	return regmap_update_bits(wusb3801->regmap, WUSB3801_REG_CTRL0,
186 				  WUSB3801_CTRL0_TRY,
187 				  wusb3801_map_try_role(role));
188 }
189 
wusb3801_port_type_set(struct typec_port * port,enum typec_port_type type)190 static int wusb3801_port_type_set(struct typec_port *port,
191 				  enum typec_port_type type)
192 {
193 	struct wusb3801 *wusb3801 = typec_get_drvdata(port);
194 	int ret;
195 
196 	ret = regmap_update_bits(wusb3801->regmap, WUSB3801_REG_CTRL0,
197 				 WUSB3801_CTRL0_ROLE,
198 				 wusb3801_map_port_type(type));
199 	if (ret)
200 		return ret;
201 
202 	wusb3801->port_type = type;
203 
204 	return 0;
205 }
206 
207 static const struct typec_operations wusb3801_typec_ops = {
208 	.try_role	= wusb3801_try_role,
209 	.port_type_set	= wusb3801_port_type_set,
210 };
211 
wusb3801_hw_init(struct wusb3801 * wusb3801)212 static int wusb3801_hw_init(struct wusb3801 *wusb3801)
213 {
214 	return regmap_write(wusb3801->regmap, WUSB3801_REG_CTRL0,
215 			    wusb3801_map_try_role(wusb3801->cap.prefer_role) |
216 			    wusb3801_map_pwr_opmode(wusb3801->pwr_opmode) |
217 			    wusb3801_map_port_type(wusb3801->port_type));
218 }
219 
wusb3801_hw_update(struct wusb3801 * wusb3801)220 static void wusb3801_hw_update(struct wusb3801 *wusb3801)
221 {
222 	struct typec_port *port = wusb3801->port;
223 	struct device *dev = wusb3801->dev;
224 	unsigned int partner_type, status;
225 	int ret;
226 
227 	ret = regmap_read(wusb3801->regmap, WUSB3801_REG_STAT, &status);
228 	if (ret) {
229 		dev_warn(dev, "Failed to read port status: %d\n", ret);
230 		status = 0;
231 	}
232 	dev_dbg(dev, "status = 0x%02x\n", status);
233 
234 	partner_type = status & WUSB3801_STAT_PARTNER;
235 
236 	if (partner_type == WUSB3801_STAT_PARTNER_SNK) {
237 		if (!wusb3801->vbus_on) {
238 			ret = regulator_enable(wusb3801->vbus_supply);
239 			if (ret)
240 				dev_warn(dev, "Failed to enable VBUS: %d\n", ret);
241 			wusb3801->vbus_on = true;
242 		}
243 	} else {
244 		if (wusb3801->vbus_on) {
245 			regulator_disable(wusb3801->vbus_supply);
246 			wusb3801->vbus_on = false;
247 		}
248 	}
249 
250 	if (partner_type != wusb3801->partner_type) {
251 		struct typec_partner_desc desc = {};
252 		enum typec_data_role data_role;
253 		enum typec_role pwr_role = wusb3801_get_default_role(wusb3801);
254 
255 		switch (partner_type) {
256 		case WUSB3801_STAT_PARTNER_STANDBY:
257 			break;
258 		case WUSB3801_STAT_PARTNER_SNK:
259 			pwr_role = TYPEC_SOURCE;
260 			break;
261 		case WUSB3801_STAT_PARTNER_SRC:
262 			pwr_role = TYPEC_SINK;
263 			break;
264 		case WUSB3801_STAT_PARTNER_AUDIO:
265 			desc.accessory = TYPEC_ACCESSORY_AUDIO;
266 			break;
267 		case WUSB3801_STAT_PARTNER_DEBUG:
268 			desc.accessory = TYPEC_ACCESSORY_DEBUG;
269 			break;
270 		}
271 
272 		if (wusb3801->partner) {
273 			typec_unregister_partner(wusb3801->partner);
274 			wusb3801->partner = NULL;
275 		}
276 
277 		if (partner_type != WUSB3801_STAT_PARTNER_STANDBY) {
278 			wusb3801->partner = typec_register_partner(port, &desc);
279 			if (IS_ERR(wusb3801->partner))
280 				dev_err(dev, "Failed to register partner: %ld\n",
281 					PTR_ERR(wusb3801->partner));
282 		}
283 
284 		data_role = pwr_role == TYPEC_SOURCE ? TYPEC_HOST : TYPEC_DEVICE;
285 		typec_set_data_role(port, data_role);
286 		typec_set_pwr_role(port, pwr_role);
287 		typec_set_vconn_role(port, pwr_role);
288 	}
289 
290 	typec_set_pwr_opmode(wusb3801->port,
291 			     partner_type == WUSB3801_STAT_PARTNER_SRC
292 				? wusb3801_unmap_pwr_opmode(status)
293 				: wusb3801->pwr_opmode);
294 	typec_set_orientation(wusb3801->port,
295 			      wusb3801_unmap_orientation(status));
296 
297 	wusb3801->partner_type = partner_type;
298 }
299 
wusb3801_irq(int irq,void * data)300 static irqreturn_t wusb3801_irq(int irq, void *data)
301 {
302 	struct wusb3801 *wusb3801 = data;
303 	unsigned int dummy;
304 
305 	/*
306 	 * The interrupt register must be read in order to clear the IRQ,
307 	 * but all of the useful information is in the status register.
308 	 */
309 	regmap_read(wusb3801->regmap, WUSB3801_REG_INT, &dummy);
310 
311 	wusb3801_hw_update(wusb3801);
312 
313 	return IRQ_HANDLED;
314 }
315 
316 static const struct regmap_config config = {
317 	.reg_bits	= 8,
318 	.val_bits	= 8,
319 	.max_register	= WUSB3801_REG_TEST12,
320 };
321 
wusb3801_probe(struct i2c_client * client)322 static int wusb3801_probe(struct i2c_client *client)
323 {
324 	struct device *dev = &client->dev;
325 	struct fwnode_handle *connector;
326 	struct wusb3801 *wusb3801;
327 	const char *cap_str;
328 	int ret;
329 
330 	wusb3801 = devm_kzalloc(dev, sizeof(*wusb3801), GFP_KERNEL);
331 	if (!wusb3801)
332 		return -ENOMEM;
333 
334 	i2c_set_clientdata(client, wusb3801);
335 
336 	wusb3801->dev = dev;
337 
338 	wusb3801->regmap = devm_regmap_init_i2c(client, &config);
339 	if (IS_ERR(wusb3801->regmap))
340 		return PTR_ERR(wusb3801->regmap);
341 
342 	wusb3801->vbus_supply = devm_regulator_get(dev, "vbus");
343 	if (IS_ERR(wusb3801->vbus_supply))
344 		return PTR_ERR(wusb3801->vbus_supply);
345 
346 	connector = device_get_named_child_node(dev, "connector");
347 	if (!connector)
348 		return -ENODEV;
349 
350 	ret = typec_get_fw_cap(&wusb3801->cap, connector);
351 	if (ret)
352 		goto err_put_connector;
353 	wusb3801->port_type = wusb3801->cap.type;
354 
355 	ret = fwnode_property_read_string(connector, "typec-power-opmode", &cap_str);
356 	if (ret)
357 		goto err_put_connector;
358 
359 	ret = typec_find_pwr_opmode(cap_str);
360 	if (ret < 0 || ret == TYPEC_PWR_MODE_PD)
361 		goto err_put_connector;
362 	wusb3801->pwr_opmode = ret;
363 
364 	/* Initialize the hardware with the devicetree settings. */
365 	ret = wusb3801_hw_init(wusb3801);
366 	if (ret)
367 		goto err_put_connector;
368 
369 	wusb3801->cap.revision		= USB_TYPEC_REV_1_2;
370 	wusb3801->cap.accessory[0]	= TYPEC_ACCESSORY_AUDIO;
371 	wusb3801->cap.accessory[1]	= TYPEC_ACCESSORY_DEBUG;
372 	wusb3801->cap.orientation_aware	= true;
373 	wusb3801->cap.driver_data	= wusb3801;
374 	wusb3801->cap.ops		= &wusb3801_typec_ops;
375 
376 	wusb3801->port = typec_register_port(dev, &wusb3801->cap);
377 	if (IS_ERR(wusb3801->port)) {
378 		ret = PTR_ERR(wusb3801->port);
379 		goto err_put_connector;
380 	}
381 
382 	/* Initialize the port attributes from the hardware state. */
383 	wusb3801_hw_update(wusb3801);
384 
385 	ret = request_threaded_irq(client->irq, NULL, wusb3801_irq,
386 				   IRQF_ONESHOT, dev_name(dev), wusb3801);
387 	if (ret)
388 		goto err_unregister_port;
389 
390 	fwnode_handle_put(connector);
391 
392 	return 0;
393 
394 err_unregister_port:
395 	typec_unregister_port(wusb3801->port);
396 err_put_connector:
397 	fwnode_handle_put(connector);
398 
399 	return ret;
400 }
401 
wusb3801_remove(struct i2c_client * client)402 static void wusb3801_remove(struct i2c_client *client)
403 {
404 	struct wusb3801 *wusb3801 = i2c_get_clientdata(client);
405 
406 	free_irq(client->irq, wusb3801);
407 
408 	if (wusb3801->partner)
409 		typec_unregister_partner(wusb3801->partner);
410 	typec_unregister_port(wusb3801->port);
411 
412 	if (wusb3801->vbus_on)
413 		regulator_disable(wusb3801->vbus_supply);
414 }
415 
416 static const struct of_device_id wusb3801_of_match[] = {
417 	{ .compatible = "willsemi,wusb3801" },
418 	{}
419 };
420 MODULE_DEVICE_TABLE(of, wusb3801_of_match);
421 
422 static struct i2c_driver wusb3801_driver = {
423 	.probe		= wusb3801_probe,
424 	.remove		= wusb3801_remove,
425 	.driver		= {
426 		.name		= "wusb3801",
427 		.of_match_table	= wusb3801_of_match,
428 	},
429 };
430 
431 module_i2c_driver(wusb3801_driver);
432 
433 MODULE_AUTHOR("Samuel Holland <samuel@sholland.org>");
434 MODULE_DESCRIPTION("Willsemi WUSB3801 Type-C port controller driver");
435 MODULE_LICENSE("GPL");
436