hc
2024-12-19 9370bb92b2d16684ee45cf24e879c93c509162da
kernel/drivers/usb/mtu3/mtu3_dr.c
....@@ -7,16 +7,11 @@
77 * Author: Chunfeng Yun <chunfeng.yun@mediatek.com>
88 */
99
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>
10
+#include <linux/usb/role.h>
1711
1812 #include "mtu3.h"
1913 #include "mtu3_dr.h"
14
+#include "mtu3_debug.h"
2015
2116 #define USB2_PORT 2
2217 #define USB3_PORT 3
....@@ -28,12 +23,26 @@
2823 MTU3_VBUS_VALID,
2924 };
3025
26
+static char *mailbox_state_string(enum mtu3_vbus_id_state state)
27
+{
28
+ switch (state) {
29
+ case MTU3_ID_FLOAT:
30
+ return "ID_FLOAT";
31
+ case MTU3_ID_GROUND:
32
+ return "ID_GROUND";
33
+ case MTU3_VBUS_OFF:
34
+ return "VBUS_OFF";
35
+ case MTU3_VBUS_VALID:
36
+ return "VBUS_VALID";
37
+ default:
38
+ return "UNKNOWN";
39
+ }
40
+}
41
+
3142 static void toggle_opstate(struct ssusb_mtk *ssusb)
3243 {
33
- if (!ssusb->otg_switch.is_u3_drd) {
34
- mtu3_setbits(ssusb->mac_base, U3D_DEVICE_CONTROL, DC_SESSION);
35
- mtu3_setbits(ssusb->mac_base, U3D_POWER_MANAGEMENT, SOFT_CONN);
36
- }
44
+ mtu3_setbits(ssusb->mac_base, U3D_DEVICE_CONTROL, DC_SESSION);
45
+ mtu3_setbits(ssusb->mac_base, U3D_POWER_MANAGEMENT, SOFT_CONN);
3746 }
3847
3948 /* only port0 supports dual-role mode */
....@@ -147,7 +156,8 @@
147156 container_of(otg_sx, struct ssusb_mtk, otg_switch);
148157 struct mtu3 *mtu = ssusb->u3d;
149158
150
- dev_dbg(ssusb->dev, "mailbox state(%d)\n", status);
159
+ dev_dbg(ssusb->dev, "mailbox %s\n", mailbox_state_string(status));
160
+ mtu3_dbg_trace(ssusb->dev, "mailbox %s", mailbox_state_string(status));
151161
152162 switch (status) {
153163 case MTU3_ID_GROUND:
....@@ -238,14 +248,18 @@
238248 otg_sx->vbus_nb.notifier_call = ssusb_vbus_notifier;
239249 ret = devm_extcon_register_notifier(ssusb->dev, edev, EXTCON_USB,
240250 &otg_sx->vbus_nb);
241
- if (ret < 0)
251
+ if (ret < 0) {
242252 dev_err(ssusb->dev, "failed to register notifier for USB\n");
253
+ return ret;
254
+ }
243255
244256 otg_sx->id_nb.notifier_call = ssusb_id_notifier;
245257 ret = devm_extcon_register_notifier(ssusb->dev, edev, EXTCON_USB_HOST,
246258 &otg_sx->id_nb);
247
- if (ret < 0)
259
+ if (ret < 0) {
248260 dev_err(ssusb->dev, "failed to register notifier for USB-HOST\n");
261
+ return ret;
262
+ }
249263
250264 dev_dbg(ssusb->dev, "EXTCON_USB: %d, EXTCON_USB_HOST: %d\n",
251265 extcon_get_state(edev, EXTCON_USB),
....@@ -266,7 +280,7 @@
266280 * This is useful in special cases, such as uses TYPE-A receptacle but also
267281 * wants to support dual-role mode.
268282 */
269
-static void ssusb_mode_manual_switch(struct ssusb_mtk *ssusb, int to_host)
283
+void ssusb_mode_switch(struct ssusb_mtk *ssusb, int to_host)
270284 {
271285 struct otg_switch_mtk *otg_sx = &ssusb->otg_switch;
272286
....@@ -279,114 +293,6 @@
279293 ssusb_set_mailbox(otg_sx, MTU3_ID_FLOAT);
280294 ssusb_set_mailbox(otg_sx, MTU3_VBUS_VALID);
281295 }
282
-}
283
-
284
-static int ssusb_mode_show(struct seq_file *sf, void *unused)
285
-{
286
- struct ssusb_mtk *ssusb = sf->private;
287
-
288
- seq_printf(sf, "current mode: %s(%s drd)\n(echo device/host)\n",
289
- ssusb->is_host ? "host" : "device",
290
- ssusb->otg_switch.manual_drd_enabled ? "manual" : "auto");
291
-
292
- return 0;
293
-}
294
-
295
-static int ssusb_mode_open(struct inode *inode, struct file *file)
296
-{
297
- return single_open(file, ssusb_mode_show, inode->i_private);
298
-}
299
-
300
-static ssize_t ssusb_mode_write(struct file *file,
301
- const char __user *ubuf, size_t count, loff_t *ppos)
302
-{
303
- struct seq_file *sf = file->private_data;
304
- struct ssusb_mtk *ssusb = sf->private;
305
- char buf[16];
306
-
307
- if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
308
- return -EFAULT;
309
-
310
- if (!strncmp(buf, "host", 4) && !ssusb->is_host) {
311
- ssusb_mode_manual_switch(ssusb, 1);
312
- } else if (!strncmp(buf, "device", 6) && ssusb->is_host) {
313
- ssusb_mode_manual_switch(ssusb, 0);
314
- } else {
315
- dev_err(ssusb->dev, "wrong or duplicated setting\n");
316
- return -EINVAL;
317
- }
318
-
319
- return count;
320
-}
321
-
322
-static const struct file_operations ssusb_mode_fops = {
323
- .open = ssusb_mode_open,
324
- .write = ssusb_mode_write,
325
- .read = seq_read,
326
- .llseek = seq_lseek,
327
- .release = single_release,
328
-};
329
-
330
-static int ssusb_vbus_show(struct seq_file *sf, void *unused)
331
-{
332
- struct ssusb_mtk *ssusb = sf->private;
333
- struct otg_switch_mtk *otg_sx = &ssusb->otg_switch;
334
-
335
- seq_printf(sf, "vbus state: %s\n(echo on/off)\n",
336
- regulator_is_enabled(otg_sx->vbus) ? "on" : "off");
337
-
338
- return 0;
339
-}
340
-
341
-static int ssusb_vbus_open(struct inode *inode, struct file *file)
342
-{
343
- return single_open(file, ssusb_vbus_show, inode->i_private);
344
-}
345
-
346
-static ssize_t ssusb_vbus_write(struct file *file,
347
- const char __user *ubuf, size_t count, loff_t *ppos)
348
-{
349
- struct seq_file *sf = file->private_data;
350
- struct ssusb_mtk *ssusb = sf->private;
351
- struct otg_switch_mtk *otg_sx = &ssusb->otg_switch;
352
- char buf[16];
353
- bool enable;
354
-
355
- if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
356
- return -EFAULT;
357
-
358
- if (kstrtobool(buf, &enable)) {
359
- dev_err(ssusb->dev, "wrong setting\n");
360
- return -EINVAL;
361
- }
362
-
363
- ssusb_set_vbus(otg_sx, enable);
364
-
365
- return count;
366
-}
367
-
368
-static const struct file_operations ssusb_vbus_fops = {
369
- .open = ssusb_vbus_open,
370
- .write = ssusb_vbus_write,
371
- .read = seq_read,
372
- .llseek = seq_lseek,
373
- .release = single_release,
374
-};
375
-
376
-static void ssusb_debugfs_init(struct ssusb_mtk *ssusb)
377
-{
378
- struct dentry *root;
379
-
380
- root = debugfs_create_dir(dev_name(ssusb->dev), usb_debug_root);
381
- ssusb->dbgfs_root = root;
382
-
383
- debugfs_create_file("mode", 0644, root, ssusb, &ssusb_mode_fops);
384
- debugfs_create_file("vbus", 0644, root, ssusb, &ssusb_vbus_fops);
385
-}
386
-
387
-static void ssusb_debugfs_exit(struct ssusb_mtk *ssusb)
388
-{
389
- debugfs_remove_recursive(ssusb->dbgfs_root);
390296 }
391297
392298 void ssusb_set_force_mode(struct ssusb_mtk *ssusb,
....@@ -412,28 +318,71 @@
412318 mtu3_writel(ssusb->ippc_base, SSUSB_U2_CTRL(0), value);
413319 }
414320
321
+static int ssusb_role_sw_set(struct usb_role_switch *sw, enum usb_role role)
322
+{
323
+ struct ssusb_mtk *ssusb = usb_role_switch_get_drvdata(sw);
324
+ bool to_host = false;
325
+
326
+ if (role == USB_ROLE_HOST)
327
+ to_host = true;
328
+
329
+ if (to_host ^ ssusb->is_host)
330
+ ssusb_mode_switch(ssusb, to_host);
331
+
332
+ return 0;
333
+}
334
+
335
+static enum usb_role ssusb_role_sw_get(struct usb_role_switch *sw)
336
+{
337
+ struct ssusb_mtk *ssusb = usb_role_switch_get_drvdata(sw);
338
+ enum usb_role role;
339
+
340
+ role = ssusb->is_host ? USB_ROLE_HOST : USB_ROLE_DEVICE;
341
+
342
+ return role;
343
+}
344
+
345
+static int ssusb_role_sw_register(struct otg_switch_mtk *otg_sx)
346
+{
347
+ struct usb_role_switch_desc role_sx_desc = { 0 };
348
+ struct ssusb_mtk *ssusb =
349
+ container_of(otg_sx, struct ssusb_mtk, otg_switch);
350
+
351
+ if (!otg_sx->role_sw_used)
352
+ return 0;
353
+
354
+ role_sx_desc.set = ssusb_role_sw_set;
355
+ role_sx_desc.get = ssusb_role_sw_get;
356
+ role_sx_desc.fwnode = dev_fwnode(ssusb->dev);
357
+ role_sx_desc.driver_data = ssusb;
358
+ otg_sx->role_sw = usb_role_switch_register(ssusb->dev, &role_sx_desc);
359
+
360
+ return PTR_ERR_OR_ZERO(otg_sx->role_sw);
361
+}
362
+
415363 int ssusb_otg_switch_init(struct ssusb_mtk *ssusb)
416364 {
417365 struct otg_switch_mtk *otg_sx = &ssusb->otg_switch;
366
+ int ret = 0;
418367
419368 INIT_WORK(&otg_sx->id_work, ssusb_id_work);
420369 INIT_WORK(&otg_sx->vbus_work, ssusb_vbus_work);
421370
422371 if (otg_sx->manual_drd_enabled)
423
- ssusb_debugfs_init(ssusb);
372
+ ssusb_dr_debugfs_init(ssusb);
373
+ else if (otg_sx->role_sw_used)
374
+ ret = ssusb_role_sw_register(otg_sx);
424375 else
425
- ssusb_extcon_register(otg_sx);
376
+ ret = ssusb_extcon_register(otg_sx);
426377
427
- return 0;
378
+ return ret;
428379 }
429380
430381 void ssusb_otg_switch_exit(struct ssusb_mtk *ssusb)
431382 {
432383 struct otg_switch_mtk *otg_sx = &ssusb->otg_switch;
433384
434
- if (otg_sx->manual_drd_enabled)
435
- ssusb_debugfs_exit(ssusb);
436
-
437385 cancel_work_sync(&otg_sx->id_work);
438386 cancel_work_sync(&otg_sx->vbus_work);
387
+ usb_role_switch_unregister(otg_sx->role_sw);
439388 }