GNU Linux-libre 6.8.7-gnu
[releases.git] / drivers / usb / typec / wusb3801.c
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
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
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
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
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
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
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
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
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
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
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
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
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
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");