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
86struct 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
99static 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
114static 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
127static 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
140static 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
153static 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
167static 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
181static 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
190static 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
207static const struct typec_operations wusb3801_typec_ops = {
208	.try_role	= wusb3801_try_role,
209	.port_type_set	= wusb3801_port_type_set,
210};
211
212static 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
220static 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
300static 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
316static const struct regmap_config config = {
317	.reg_bits	= 8,
318	.val_bits	= 8,
319	.max_register	= WUSB3801_REG_TEST12,
320};
321
322static 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
394err_unregister_port:
395	typec_unregister_port(wusb3801->port);
396err_put_connector:
397	fwnode_handle_put(connector);
398
399	return ret;
400}
401
402static 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
416static const struct of_device_id wusb3801_of_match[] = {
417	{ .compatible = "willsemi,wusb3801" },
418	{}
419};
420MODULE_DEVICE_TABLE(of, wusb3801_of_match);
421
422static 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
431module_i2c_driver(wusb3801_driver);
432
433MODULE_AUTHOR("Samuel Holland <samuel@sholland.org>");
434MODULE_DESCRIPTION("Willsemi WUSB3801 Type-C port controller driver");
435MODULE_LICENSE("GPL");
436