GNU Linux-libre 4.19.281-gnu1
[releases.git] / drivers / usb / mtu3 / mtu3_dr.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * mtu3_dr.c - dual role switch and host glue layer
4  *
5  * Copyright (C) 2016 MediaTek Inc.
6  *
7  * Author: Chunfeng Yun <chunfeng.yun@mediatek.com>
8  */
9
10 #include <linux/debugfs.h>
11 #include <linux/irq.h>
12 #include <linux/kernel.h>
13 #include <linux/of_device.h>
14 #include <linux/pinctrl/consumer.h>
15 #include <linux/seq_file.h>
16 #include <linux/uaccess.h>
17
18 #include "mtu3.h"
19 #include "mtu3_dr.h"
20
21 #define USB2_PORT 2
22 #define USB3_PORT 3
23
24 enum mtu3_vbus_id_state {
25         MTU3_ID_FLOAT = 1,
26         MTU3_ID_GROUND,
27         MTU3_VBUS_OFF,
28         MTU3_VBUS_VALID,
29 };
30
31 static void toggle_opstate(struct ssusb_mtk *ssusb)
32 {
33         mtu3_setbits(ssusb->mac_base, U3D_DEVICE_CONTROL, DC_SESSION);
34         mtu3_setbits(ssusb->mac_base, U3D_POWER_MANAGEMENT, SOFT_CONN);
35 }
36
37 /* only port0 supports dual-role mode */
38 static int ssusb_port0_switch(struct ssusb_mtk *ssusb,
39         int version, bool tohost)
40 {
41         void __iomem *ibase = ssusb->ippc_base;
42         u32 value;
43
44         dev_dbg(ssusb->dev, "%s (switch u%d port0 to %s)\n", __func__,
45                 version, tohost ? "host" : "device");
46
47         if (version == USB2_PORT) {
48                 /* 1. power off and disable u2 port0 */
49                 value = mtu3_readl(ibase, SSUSB_U2_CTRL(0));
50                 value |= SSUSB_U2_PORT_PDN | SSUSB_U2_PORT_DIS;
51                 mtu3_writel(ibase, SSUSB_U2_CTRL(0), value);
52
53                 /* 2. power on, enable u2 port0 and select its mode */
54                 value = mtu3_readl(ibase, SSUSB_U2_CTRL(0));
55                 value &= ~(SSUSB_U2_PORT_PDN | SSUSB_U2_PORT_DIS);
56                 value = tohost ? (value | SSUSB_U2_PORT_HOST_SEL) :
57                         (value & (~SSUSB_U2_PORT_HOST_SEL));
58                 mtu3_writel(ibase, SSUSB_U2_CTRL(0), value);
59         } else {
60                 /* 1. power off and disable u3 port0 */
61                 value = mtu3_readl(ibase, SSUSB_U3_CTRL(0));
62                 value |= SSUSB_U3_PORT_PDN | SSUSB_U3_PORT_DIS;
63                 mtu3_writel(ibase, SSUSB_U3_CTRL(0), value);
64
65                 /* 2. power on, enable u3 port0 and select its mode */
66                 value = mtu3_readl(ibase, SSUSB_U3_CTRL(0));
67                 value &= ~(SSUSB_U3_PORT_PDN | SSUSB_U3_PORT_DIS);
68                 value = tohost ? (value | SSUSB_U3_PORT_HOST_SEL) :
69                         (value & (~SSUSB_U3_PORT_HOST_SEL));
70                 mtu3_writel(ibase, SSUSB_U3_CTRL(0), value);
71         }
72
73         return 0;
74 }
75
76 static void switch_port_to_host(struct ssusb_mtk *ssusb)
77 {
78         u32 check_clk = 0;
79
80         dev_dbg(ssusb->dev, "%s\n", __func__);
81
82         ssusb_port0_switch(ssusb, USB2_PORT, true);
83
84         if (ssusb->otg_switch.is_u3_drd) {
85                 ssusb_port0_switch(ssusb, USB3_PORT, true);
86                 check_clk = SSUSB_U3_MAC_RST_B_STS;
87         }
88
89         ssusb_check_clocks(ssusb, check_clk);
90
91         /* after all clocks are stable */
92         toggle_opstate(ssusb);
93 }
94
95 static void switch_port_to_device(struct ssusb_mtk *ssusb)
96 {
97         u32 check_clk = 0;
98
99         dev_dbg(ssusb->dev, "%s\n", __func__);
100
101         ssusb_port0_switch(ssusb, USB2_PORT, false);
102
103         if (ssusb->otg_switch.is_u3_drd) {
104                 ssusb_port0_switch(ssusb, USB3_PORT, false);
105                 check_clk = SSUSB_U3_MAC_RST_B_STS;
106         }
107
108         ssusb_check_clocks(ssusb, check_clk);
109 }
110
111 int ssusb_set_vbus(struct otg_switch_mtk *otg_sx, int is_on)
112 {
113         struct ssusb_mtk *ssusb =
114                 container_of(otg_sx, struct ssusb_mtk, otg_switch);
115         struct regulator *vbus = otg_sx->vbus;
116         int ret;
117
118         /* vbus is optional */
119         if (!vbus)
120                 return 0;
121
122         dev_dbg(ssusb->dev, "%s: turn %s\n", __func__, is_on ? "on" : "off");
123
124         if (is_on) {
125                 ret = regulator_enable(vbus);
126                 if (ret) {
127                         dev_err(ssusb->dev, "vbus regulator enable failed\n");
128                         return ret;
129                 }
130         } else {
131                 regulator_disable(vbus);
132         }
133
134         return 0;
135 }
136
137 /*
138  * switch to host: -> MTU3_VBUS_OFF --> MTU3_ID_GROUND
139  * switch to device: -> MTU3_ID_FLOAT --> MTU3_VBUS_VALID
140  */
141 static void ssusb_set_mailbox(struct otg_switch_mtk *otg_sx,
142         enum mtu3_vbus_id_state status)
143 {
144         struct ssusb_mtk *ssusb =
145                 container_of(otg_sx, struct ssusb_mtk, otg_switch);
146         struct mtu3 *mtu = ssusb->u3d;
147
148         dev_dbg(ssusb->dev, "mailbox state(%d)\n", status);
149
150         switch (status) {
151         case MTU3_ID_GROUND:
152                 switch_port_to_host(ssusb);
153                 ssusb_set_vbus(otg_sx, 1);
154                 ssusb->is_host = true;
155                 break;
156         case MTU3_ID_FLOAT:
157                 ssusb->is_host = false;
158                 ssusb_set_vbus(otg_sx, 0);
159                 switch_port_to_device(ssusb);
160                 break;
161         case MTU3_VBUS_OFF:
162                 mtu3_stop(mtu);
163                 pm_relax(ssusb->dev);
164                 break;
165         case MTU3_VBUS_VALID:
166                 /* avoid suspend when works as device */
167                 pm_stay_awake(ssusb->dev);
168                 mtu3_start(mtu);
169                 break;
170         default:
171                 dev_err(ssusb->dev, "invalid state\n");
172         }
173 }
174
175 static void ssusb_id_work(struct work_struct *work)
176 {
177         struct otg_switch_mtk *otg_sx =
178                 container_of(work, struct otg_switch_mtk, id_work);
179
180         if (otg_sx->id_event)
181                 ssusb_set_mailbox(otg_sx, MTU3_ID_GROUND);
182         else
183                 ssusb_set_mailbox(otg_sx, MTU3_ID_FLOAT);
184 }
185
186 static void ssusb_vbus_work(struct work_struct *work)
187 {
188         struct otg_switch_mtk *otg_sx =
189                 container_of(work, struct otg_switch_mtk, vbus_work);
190
191         if (otg_sx->vbus_event)
192                 ssusb_set_mailbox(otg_sx, MTU3_VBUS_VALID);
193         else
194                 ssusb_set_mailbox(otg_sx, MTU3_VBUS_OFF);
195 }
196
197 /*
198  * @ssusb_id_notifier is called in atomic context, but @ssusb_set_mailbox
199  * may sleep, so use work queue here
200  */
201 static int ssusb_id_notifier(struct notifier_block *nb,
202         unsigned long event, void *ptr)
203 {
204         struct otg_switch_mtk *otg_sx =
205                 container_of(nb, struct otg_switch_mtk, id_nb);
206
207         otg_sx->id_event = event;
208         schedule_work(&otg_sx->id_work);
209
210         return NOTIFY_DONE;
211 }
212
213 static int ssusb_vbus_notifier(struct notifier_block *nb,
214         unsigned long event, void *ptr)
215 {
216         struct otg_switch_mtk *otg_sx =
217                 container_of(nb, struct otg_switch_mtk, vbus_nb);
218
219         otg_sx->vbus_event = event;
220         schedule_work(&otg_sx->vbus_work);
221
222         return NOTIFY_DONE;
223 }
224
225 static int ssusb_extcon_register(struct otg_switch_mtk *otg_sx)
226 {
227         struct ssusb_mtk *ssusb =
228                 container_of(otg_sx, struct ssusb_mtk, otg_switch);
229         struct extcon_dev *edev = otg_sx->edev;
230         int ret;
231
232         /* extcon is optional */
233         if (!edev)
234                 return 0;
235
236         otg_sx->vbus_nb.notifier_call = ssusb_vbus_notifier;
237         ret = devm_extcon_register_notifier(ssusb->dev, edev, EXTCON_USB,
238                                         &otg_sx->vbus_nb);
239         if (ret < 0)
240                 dev_err(ssusb->dev, "failed to register notifier for USB\n");
241
242         otg_sx->id_nb.notifier_call = ssusb_id_notifier;
243         ret = devm_extcon_register_notifier(ssusb->dev, edev, EXTCON_USB_HOST,
244                                         &otg_sx->id_nb);
245         if (ret < 0)
246                 dev_err(ssusb->dev, "failed to register notifier for USB-HOST\n");
247
248         dev_dbg(ssusb->dev, "EXTCON_USB: %d, EXTCON_USB_HOST: %d\n",
249                 extcon_get_state(edev, EXTCON_USB),
250                 extcon_get_state(edev, EXTCON_USB_HOST));
251
252         /* default as host, switch to device mode if needed */
253         if (extcon_get_state(edev, EXTCON_USB_HOST) == false)
254                 ssusb_set_mailbox(otg_sx, MTU3_ID_FLOAT);
255         if (extcon_get_state(edev, EXTCON_USB) == true)
256                 ssusb_set_mailbox(otg_sx, MTU3_VBUS_VALID);
257
258         return 0;
259 }
260
261 /*
262  * We provide an interface via debugfs to switch between host and device modes
263  * depending on user input.
264  * This is useful in special cases, such as uses TYPE-A receptacle but also
265  * wants to support dual-role mode.
266  */
267 static void ssusb_mode_manual_switch(struct ssusb_mtk *ssusb, int to_host)
268 {
269         struct otg_switch_mtk *otg_sx = &ssusb->otg_switch;
270
271         if (to_host) {
272                 ssusb_set_force_mode(ssusb, MTU3_DR_FORCE_HOST);
273                 ssusb_set_mailbox(otg_sx, MTU3_VBUS_OFF);
274                 ssusb_set_mailbox(otg_sx, MTU3_ID_GROUND);
275         } else {
276                 ssusb_set_force_mode(ssusb, MTU3_DR_FORCE_DEVICE);
277                 ssusb_set_mailbox(otg_sx, MTU3_ID_FLOAT);
278                 ssusb_set_mailbox(otg_sx, MTU3_VBUS_VALID);
279         }
280 }
281
282 static int ssusb_mode_show(struct seq_file *sf, void *unused)
283 {
284         struct ssusb_mtk *ssusb = sf->private;
285
286         seq_printf(sf, "current mode: %s(%s drd)\n(echo device/host)\n",
287                 ssusb->is_host ? "host" : "device",
288                 ssusb->otg_switch.manual_drd_enabled ? "manual" : "auto");
289
290         return 0;
291 }
292
293 static int ssusb_mode_open(struct inode *inode, struct file *file)
294 {
295         return single_open(file, ssusb_mode_show, inode->i_private);
296 }
297
298 static ssize_t ssusb_mode_write(struct file *file,
299         const char __user *ubuf, size_t count, loff_t *ppos)
300 {
301         struct seq_file *sf = file->private_data;
302         struct ssusb_mtk *ssusb = sf->private;
303         char buf[16];
304
305         if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
306                 return -EFAULT;
307
308         if (!strncmp(buf, "host", 4) && !ssusb->is_host) {
309                 ssusb_mode_manual_switch(ssusb, 1);
310         } else if (!strncmp(buf, "device", 6) && ssusb->is_host) {
311                 ssusb_mode_manual_switch(ssusb, 0);
312         } else {
313                 dev_err(ssusb->dev, "wrong or duplicated setting\n");
314                 return -EINVAL;
315         }
316
317         return count;
318 }
319
320 static const struct file_operations ssusb_mode_fops = {
321         .open = ssusb_mode_open,
322         .write = ssusb_mode_write,
323         .read = seq_read,
324         .llseek = seq_lseek,
325         .release = single_release,
326 };
327
328 static int ssusb_vbus_show(struct seq_file *sf, void *unused)
329 {
330         struct ssusb_mtk *ssusb = sf->private;
331         struct otg_switch_mtk *otg_sx = &ssusb->otg_switch;
332
333         seq_printf(sf, "vbus state: %s\n(echo on/off)\n",
334                 regulator_is_enabled(otg_sx->vbus) ? "on" : "off");
335
336         return 0;
337 }
338
339 static int ssusb_vbus_open(struct inode *inode, struct file *file)
340 {
341         return single_open(file, ssusb_vbus_show, inode->i_private);
342 }
343
344 static ssize_t ssusb_vbus_write(struct file *file,
345         const char __user *ubuf, size_t count, loff_t *ppos)
346 {
347         struct seq_file *sf = file->private_data;
348         struct ssusb_mtk *ssusb = sf->private;
349         struct otg_switch_mtk *otg_sx = &ssusb->otg_switch;
350         char buf[16];
351         bool enable;
352
353         if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
354                 return -EFAULT;
355
356         if (kstrtobool(buf, &enable)) {
357                 dev_err(ssusb->dev, "wrong setting\n");
358                 return -EINVAL;
359         }
360
361         ssusb_set_vbus(otg_sx, enable);
362
363         return count;
364 }
365
366 static const struct file_operations ssusb_vbus_fops = {
367         .open = ssusb_vbus_open,
368         .write = ssusb_vbus_write,
369         .read = seq_read,
370         .llseek = seq_lseek,
371         .release = single_release,
372 };
373
374 static void ssusb_debugfs_init(struct ssusb_mtk *ssusb)
375 {
376         struct dentry *root;
377
378         root = debugfs_create_dir(dev_name(ssusb->dev), usb_debug_root);
379         ssusb->dbgfs_root = root;
380
381         debugfs_create_file("mode", 0644, root, ssusb, &ssusb_mode_fops);
382         debugfs_create_file("vbus", 0644, root, ssusb, &ssusb_vbus_fops);
383 }
384
385 static void ssusb_debugfs_exit(struct ssusb_mtk *ssusb)
386 {
387         debugfs_remove_recursive(ssusb->dbgfs_root);
388 }
389
390 void ssusb_set_force_mode(struct ssusb_mtk *ssusb,
391                           enum mtu3_dr_force_mode mode)
392 {
393         u32 value;
394
395         value = mtu3_readl(ssusb->ippc_base, SSUSB_U2_CTRL(0));
396         switch (mode) {
397         case MTU3_DR_FORCE_DEVICE:
398                 value |= SSUSB_U2_PORT_FORCE_IDDIG | SSUSB_U2_PORT_RG_IDDIG;
399                 break;
400         case MTU3_DR_FORCE_HOST:
401                 value |= SSUSB_U2_PORT_FORCE_IDDIG;
402                 value &= ~SSUSB_U2_PORT_RG_IDDIG;
403                 break;
404         case MTU3_DR_FORCE_NONE:
405                 value &= ~(SSUSB_U2_PORT_FORCE_IDDIG | SSUSB_U2_PORT_RG_IDDIG);
406                 break;
407         default:
408                 return;
409         }
410         mtu3_writel(ssusb->ippc_base, SSUSB_U2_CTRL(0), value);
411 }
412
413 int ssusb_otg_switch_init(struct ssusb_mtk *ssusb)
414 {
415         struct otg_switch_mtk *otg_sx = &ssusb->otg_switch;
416
417         INIT_WORK(&otg_sx->id_work, ssusb_id_work);
418         INIT_WORK(&otg_sx->vbus_work, ssusb_vbus_work);
419
420         if (otg_sx->manual_drd_enabled)
421                 ssusb_debugfs_init(ssusb);
422         else
423                 ssusb_extcon_register(otg_sx);
424
425         return 0;
426 }
427
428 void ssusb_otg_switch_exit(struct ssusb_mtk *ssusb)
429 {
430         struct otg_switch_mtk *otg_sx = &ssusb->otg_switch;
431
432         if (otg_sx->manual_drd_enabled)
433                 ssusb_debugfs_exit(ssusb);
434
435         cancel_work_sync(&otg_sx->id_work);
436         cancel_work_sync(&otg_sx->vbus_work);
437 }