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