.. | .. |
---|
352 | 352 | int disabled_count; |
---|
353 | 353 | |
---|
354 | 354 | struct usb_request *ep0_req; |
---|
| 355 | + |
---|
| 356 | + enum usb_role connection_state; |
---|
355 | 357 | u16 test_mode; |
---|
356 | 358 | u8 ep0_buf[USB3_EP0_BUF_SIZE]; |
---|
357 | 359 | bool softconnect; |
---|
.. | .. |
---|
360 | 362 | bool extcon_usb; /* check vbus and set EXTCON_USB */ |
---|
361 | 363 | bool forced_b_device; |
---|
362 | 364 | bool start_to_connect; |
---|
| 365 | + bool role_sw_by_connector; |
---|
363 | 366 | }; |
---|
364 | 367 | |
---|
365 | 368 | #define gadget_to_renesas_usb3(_gadget) \ |
---|
.. | .. |
---|
700 | 703 | unsigned long flags; |
---|
701 | 704 | |
---|
702 | 705 | spin_lock_irqsave(&usb3->lock, flags); |
---|
703 | | - usb3_set_mode_by_role_sw(usb3, host); |
---|
704 | | - usb3_vbus_out(usb3, a_dev); |
---|
| 706 | + if (!usb3->role_sw_by_connector || |
---|
| 707 | + usb3->connection_state != USB_ROLE_NONE) { |
---|
| 708 | + usb3_set_mode_by_role_sw(usb3, host); |
---|
| 709 | + usb3_vbus_out(usb3, a_dev); |
---|
| 710 | + } |
---|
705 | 711 | /* for A-Peripheral or forced B-device mode */ |
---|
706 | 712 | if ((!host && a_dev) || usb3->start_to_connect) |
---|
707 | 713 | usb3_connect(usb3); |
---|
.. | .. |
---|
717 | 723 | { |
---|
718 | 724 | usb3->extcon_host = usb3_is_a_device(usb3); |
---|
719 | 725 | |
---|
720 | | - if (usb3->extcon_host && !usb3->forced_b_device) |
---|
| 726 | + if ((!usb3->role_sw_by_connector && usb3->extcon_host && |
---|
| 727 | + !usb3->forced_b_device) || usb3->connection_state == USB_ROLE_HOST) |
---|
721 | 728 | usb3_mode_config(usb3, true, true); |
---|
722 | 729 | else |
---|
723 | 730 | usb3_mode_config(usb3, false, false); |
---|
.. | .. |
---|
766 | 773 | usb3_disable_irq_1(usb3, USB_INT_1_B2_RSUM); |
---|
767 | 774 | usb3_start_usb2_connection(usb3); |
---|
768 | 775 | usb3_transition_to_default_state(usb3, false); |
---|
| 776 | +} |
---|
| 777 | + |
---|
| 778 | +static void usb3_irq_epc_int_1_suspend(struct renesas_usb3 *usb3) |
---|
| 779 | +{ |
---|
| 780 | + usb3_disable_irq_1(usb3, USB_INT_1_B2_SPND); |
---|
| 781 | + |
---|
| 782 | + if (usb3->gadget.speed != USB_SPEED_UNKNOWN && |
---|
| 783 | + usb3->gadget.state != USB_STATE_NOTATTACHED) { |
---|
| 784 | + if (usb3->driver && usb3->driver->suspend) |
---|
| 785 | + usb3->driver->suspend(&usb3->gadget); |
---|
| 786 | + usb_gadget_set_state(&usb3->gadget, USB_STATE_SUSPENDED); |
---|
| 787 | + } |
---|
769 | 788 | } |
---|
770 | 789 | |
---|
771 | 790 | static void usb3_irq_epc_int_1_disable(struct renesas_usb3 *usb3) |
---|
.. | .. |
---|
852 | 871 | |
---|
853 | 872 | if (int_sta_1 & USB_INT_1_B2_RSUM) |
---|
854 | 873 | usb3_irq_epc_int_1_resume(usb3); |
---|
| 874 | + |
---|
| 875 | + if (int_sta_1 & USB_INT_1_B2_SPND) |
---|
| 876 | + usb3_irq_epc_int_1_suspend(usb3); |
---|
855 | 877 | |
---|
856 | 878 | if (int_sta_1 & USB_INT_1_SPEED) |
---|
857 | 879 | usb3_irq_epc_int_1_speed(usb3); |
---|
.. | .. |
---|
1162 | 1184 | static void usb3_p0_xfer(struct renesas_usb3_ep *usb3_ep, |
---|
1163 | 1185 | struct renesas_usb3_request *usb3_req) |
---|
1164 | 1186 | { |
---|
1165 | | - int ret = -EAGAIN; |
---|
| 1187 | + int ret; |
---|
1166 | 1188 | |
---|
1167 | 1189 | if (usb3_ep->dir_in) |
---|
1168 | 1190 | ret = usb3_write_pipe(usb3_ep, usb3_req, USB3_P0_WRITE); |
---|
.. | .. |
---|
1538 | 1560 | static bool usb3_std_req_set_address(struct renesas_usb3 *usb3, |
---|
1539 | 1561 | struct usb_ctrlrequest *ctrl) |
---|
1540 | 1562 | { |
---|
1541 | | - if (ctrl->wValue >= 128) |
---|
| 1563 | + if (le16_to_cpu(ctrl->wValue) >= 128) |
---|
1542 | 1564 | return true; /* stall */ |
---|
1543 | 1565 | |
---|
1544 | | - usb3_set_device_address(usb3, ctrl->wValue); |
---|
| 1566 | + usb3_set_device_address(usb3, le16_to_cpu(ctrl->wValue)); |
---|
1545 | 1567 | usb3_set_p0_con_for_no_data(usb3); |
---|
1546 | 1568 | |
---|
1547 | 1569 | return false; |
---|
.. | .. |
---|
1576 | 1598 | struct renesas_usb3_ep *usb3_ep; |
---|
1577 | 1599 | int num; |
---|
1578 | 1600 | u16 status = 0; |
---|
| 1601 | + __le16 tx_data; |
---|
1579 | 1602 | |
---|
1580 | 1603 | switch (ctrl->bRequestType & USB_RECIP_MASK) { |
---|
1581 | 1604 | case USB_RECIP_DEVICE: |
---|
.. | .. |
---|
1598 | 1621 | } |
---|
1599 | 1622 | |
---|
1600 | 1623 | if (!stall) { |
---|
1601 | | - status = cpu_to_le16(status); |
---|
| 1624 | + tx_data = cpu_to_le16(status); |
---|
1602 | 1625 | dev_dbg(usb3_to_dev(usb3), "get_status: req = %p\n", |
---|
1603 | 1626 | usb_req_to_usb3_req(usb3->ep0_req)); |
---|
1604 | | - usb3_pipe0_internal_xfer(usb3, &status, sizeof(status), |
---|
| 1627 | + usb3_pipe0_internal_xfer(usb3, &tx_data, sizeof(tx_data), |
---|
1605 | 1628 | usb3_pipe0_get_status_completion); |
---|
1606 | 1629 | } |
---|
1607 | 1630 | |
---|
.. | .. |
---|
1766 | 1789 | static bool usb3_std_req_set_configuration(struct renesas_usb3 *usb3, |
---|
1767 | 1790 | struct usb_ctrlrequest *ctrl) |
---|
1768 | 1791 | { |
---|
1769 | | - if (ctrl->wValue > 0) |
---|
| 1792 | + if (le16_to_cpu(ctrl->wValue) > 0) |
---|
1770 | 1793 | usb3_set_bit(usb3, USB_COM_CON_CONF, USB3_USB_COM_CON); |
---|
1771 | 1794 | else |
---|
1772 | 1795 | usb3_clear_bit(usb3, USB_COM_CON_CONF, USB3_USB_COM_CON); |
---|
.. | .. |
---|
2333 | 2356 | .set_selfpowered = renesas_usb3_set_selfpowered, |
---|
2334 | 2357 | }; |
---|
2335 | 2358 | |
---|
2336 | | -static enum usb_role renesas_usb3_role_switch_get(struct device *dev) |
---|
| 2359 | +static enum usb_role renesas_usb3_role_switch_get(struct usb_role_switch *sw) |
---|
2337 | 2360 | { |
---|
2338 | | - struct renesas_usb3 *usb3 = dev_get_drvdata(dev); |
---|
| 2361 | + struct renesas_usb3 *usb3 = usb_role_switch_get_drvdata(sw); |
---|
2339 | 2362 | enum usb_role cur_role; |
---|
2340 | 2363 | |
---|
2341 | | - pm_runtime_get_sync(dev); |
---|
| 2364 | + pm_runtime_get_sync(usb3_to_dev(usb3)); |
---|
2342 | 2365 | cur_role = usb3_is_host(usb3) ? USB_ROLE_HOST : USB_ROLE_DEVICE; |
---|
2343 | | - pm_runtime_put(dev); |
---|
| 2366 | + pm_runtime_put(usb3_to_dev(usb3)); |
---|
2344 | 2367 | |
---|
2345 | 2368 | return cur_role; |
---|
2346 | 2369 | } |
---|
2347 | 2370 | |
---|
2348 | | -static int renesas_usb3_role_switch_set(struct device *dev, |
---|
2349 | | - enum usb_role role) |
---|
| 2371 | +static void handle_ext_role_switch_states(struct device *dev, |
---|
| 2372 | + enum usb_role role) |
---|
2350 | 2373 | { |
---|
2351 | 2374 | struct renesas_usb3 *usb3 = dev_get_drvdata(dev); |
---|
2352 | 2375 | struct device *host = usb3->host_dev; |
---|
2353 | | - enum usb_role cur_role = renesas_usb3_role_switch_get(dev); |
---|
| 2376 | + enum usb_role cur_role = renesas_usb3_role_switch_get(usb3->role_sw); |
---|
2354 | 2377 | |
---|
2355 | | - pm_runtime_get_sync(dev); |
---|
| 2378 | + switch (role) { |
---|
| 2379 | + case USB_ROLE_NONE: |
---|
| 2380 | + usb3->connection_state = USB_ROLE_NONE; |
---|
| 2381 | + if (cur_role == USB_ROLE_HOST) |
---|
| 2382 | + device_release_driver(host); |
---|
| 2383 | + if (usb3->driver) |
---|
| 2384 | + usb3_disconnect(usb3); |
---|
| 2385 | + usb3_vbus_out(usb3, false); |
---|
| 2386 | + break; |
---|
| 2387 | + case USB_ROLE_DEVICE: |
---|
| 2388 | + if (usb3->connection_state == USB_ROLE_NONE) { |
---|
| 2389 | + usb3->connection_state = USB_ROLE_DEVICE; |
---|
| 2390 | + usb3_set_mode(usb3, false); |
---|
| 2391 | + if (usb3->driver) |
---|
| 2392 | + usb3_connect(usb3); |
---|
| 2393 | + } else if (cur_role == USB_ROLE_HOST) { |
---|
| 2394 | + device_release_driver(host); |
---|
| 2395 | + usb3_set_mode(usb3, false); |
---|
| 2396 | + if (usb3->driver) |
---|
| 2397 | + usb3_connect(usb3); |
---|
| 2398 | + } |
---|
| 2399 | + usb3_vbus_out(usb3, false); |
---|
| 2400 | + break; |
---|
| 2401 | + case USB_ROLE_HOST: |
---|
| 2402 | + if (usb3->connection_state == USB_ROLE_NONE) { |
---|
| 2403 | + if (usb3->driver) |
---|
| 2404 | + usb3_disconnect(usb3); |
---|
| 2405 | + |
---|
| 2406 | + usb3->connection_state = USB_ROLE_HOST; |
---|
| 2407 | + usb3_set_mode(usb3, true); |
---|
| 2408 | + usb3_vbus_out(usb3, true); |
---|
| 2409 | + if (device_attach(host) < 0) |
---|
| 2410 | + dev_err(dev, "device_attach(host) failed\n"); |
---|
| 2411 | + } else if (cur_role == USB_ROLE_DEVICE) { |
---|
| 2412 | + usb3_disconnect(usb3); |
---|
| 2413 | + /* Must set the mode before device_attach of the host */ |
---|
| 2414 | + usb3_set_mode(usb3, true); |
---|
| 2415 | + /* This device_attach() might sleep */ |
---|
| 2416 | + if (device_attach(host) < 0) |
---|
| 2417 | + dev_err(dev, "device_attach(host) failed\n"); |
---|
| 2418 | + } |
---|
| 2419 | + break; |
---|
| 2420 | + default: |
---|
| 2421 | + break; |
---|
| 2422 | + } |
---|
| 2423 | +} |
---|
| 2424 | + |
---|
| 2425 | +static void handle_role_switch_states(struct device *dev, |
---|
| 2426 | + enum usb_role role) |
---|
| 2427 | +{ |
---|
| 2428 | + struct renesas_usb3 *usb3 = dev_get_drvdata(dev); |
---|
| 2429 | + struct device *host = usb3->host_dev; |
---|
| 2430 | + enum usb_role cur_role = renesas_usb3_role_switch_get(usb3->role_sw); |
---|
| 2431 | + |
---|
2356 | 2432 | if (cur_role == USB_ROLE_HOST && role == USB_ROLE_DEVICE) { |
---|
2357 | 2433 | device_release_driver(host); |
---|
2358 | 2434 | usb3_set_mode(usb3, false); |
---|
.. | .. |
---|
2363 | 2439 | if (device_attach(host) < 0) |
---|
2364 | 2440 | dev_err(dev, "device_attach(host) failed\n"); |
---|
2365 | 2441 | } |
---|
2366 | | - pm_runtime_put(dev); |
---|
| 2442 | +} |
---|
| 2443 | + |
---|
| 2444 | +static int renesas_usb3_role_switch_set(struct usb_role_switch *sw, |
---|
| 2445 | + enum usb_role role) |
---|
| 2446 | +{ |
---|
| 2447 | + struct renesas_usb3 *usb3 = usb_role_switch_get_drvdata(sw); |
---|
| 2448 | + |
---|
| 2449 | + pm_runtime_get_sync(usb3_to_dev(usb3)); |
---|
| 2450 | + |
---|
| 2451 | + if (usb3->role_sw_by_connector) |
---|
| 2452 | + handle_ext_role_switch_states(usb3_to_dev(usb3), role); |
---|
| 2453 | + else |
---|
| 2454 | + handle_role_switch_states(usb3_to_dev(usb3), role); |
---|
| 2455 | + |
---|
| 2456 | + pm_runtime_put(usb3_to_dev(usb3)); |
---|
2367 | 2457 | |
---|
2368 | 2458 | return 0; |
---|
2369 | 2459 | } |
---|
.. | .. |
---|
2464 | 2554 | static void renesas_usb3_debugfs_init(struct renesas_usb3 *usb3, |
---|
2465 | 2555 | struct device *dev) |
---|
2466 | 2556 | { |
---|
2467 | | - usb3->dentry = debugfs_create_dir(dev_name(dev), NULL); |
---|
| 2557 | + usb3->dentry = debugfs_create_dir(dev_name(dev), usb_debug_root); |
---|
2468 | 2558 | |
---|
2469 | 2559 | debugfs_create_file("b_device", 0644, usb3->dentry, usb3, |
---|
2470 | 2560 | &renesas_usb3_b_device_fops); |
---|
.. | .. |
---|
2478 | 2568 | debugfs_remove_recursive(usb3->dentry); |
---|
2479 | 2569 | device_remove_file(&pdev->dev, &dev_attr_role); |
---|
2480 | 2570 | |
---|
| 2571 | + cancel_work_sync(&usb3->role_work); |
---|
2481 | 2572 | usb_role_switch_unregister(usb3->role_sw); |
---|
2482 | 2573 | |
---|
2483 | 2574 | usb_del_gadget_udc(&usb3->gadget); |
---|
.. | .. |
---|
2610 | 2701 | .ramsize_per_pipe = SZ_4K, |
---|
2611 | 2702 | }; |
---|
2612 | 2703 | |
---|
| 2704 | +static const struct renesas_usb3_priv renesas_usb3_priv_r8a77990 = { |
---|
| 2705 | + .ramsize_per_ramif = SZ_16K, |
---|
| 2706 | + .num_ramif = 4, |
---|
| 2707 | + .ramsize_per_pipe = SZ_4K, |
---|
| 2708 | + .workaround_for_vbus = true, |
---|
| 2709 | +}; |
---|
| 2710 | + |
---|
2613 | 2711 | static const struct of_device_id usb3_of_match[] = { |
---|
2614 | 2712 | { |
---|
| 2713 | + .compatible = "renesas,r8a774c0-usb3-peri", |
---|
| 2714 | + .data = &renesas_usb3_priv_r8a77990, |
---|
| 2715 | + }, { |
---|
2615 | 2716 | .compatible = "renesas,r8a7795-usb3-peri", |
---|
2616 | 2717 | .data = &renesas_usb3_priv_gen3, |
---|
2617 | | - }, |
---|
2618 | | - { |
---|
| 2718 | + }, { |
---|
| 2719 | + .compatible = "renesas,r8a77990-usb3-peri", |
---|
| 2720 | + .data = &renesas_usb3_priv_r8a77990, |
---|
| 2721 | + }, { |
---|
2619 | 2722 | .compatible = "renesas,rcar-gen3-usb3-peri", |
---|
2620 | 2723 | .data = &renesas_usb3_priv_gen3, |
---|
2621 | 2724 | }, |
---|
.. | .. |
---|
2637 | 2740 | EXTCON_NONE, |
---|
2638 | 2741 | }; |
---|
2639 | 2742 | |
---|
2640 | | -static const struct usb_role_switch_desc renesas_usb3_role_switch_desc = { |
---|
| 2743 | +static struct usb_role_switch_desc renesas_usb3_role_switch_desc = { |
---|
2641 | 2744 | .set = renesas_usb3_role_switch_set, |
---|
2642 | 2745 | .get = renesas_usb3_role_switch_get, |
---|
2643 | 2746 | .allow_userspace_control = true, |
---|
.. | .. |
---|
2646 | 2749 | static int renesas_usb3_probe(struct platform_device *pdev) |
---|
2647 | 2750 | { |
---|
2648 | 2751 | struct renesas_usb3 *usb3; |
---|
2649 | | - struct resource *res; |
---|
2650 | 2752 | int irq, ret; |
---|
2651 | 2753 | const struct renesas_usb3_priv *priv; |
---|
2652 | 2754 | const struct soc_device_attribute *attr; |
---|
.. | .. |
---|
2658 | 2760 | priv = of_device_get_match_data(&pdev->dev); |
---|
2659 | 2761 | |
---|
2660 | 2762 | irq = platform_get_irq(pdev, 0); |
---|
2661 | | - if (irq < 0) { |
---|
2662 | | - dev_err(&pdev->dev, "Failed to get IRQ: %d\n", irq); |
---|
| 2763 | + if (irq < 0) |
---|
2663 | 2764 | return irq; |
---|
2664 | | - } |
---|
2665 | 2765 | |
---|
2666 | 2766 | usb3 = devm_kzalloc(&pdev->dev, sizeof(*usb3), GFP_KERNEL); |
---|
2667 | 2767 | if (!usb3) |
---|
2668 | 2768 | return -ENOMEM; |
---|
2669 | 2769 | |
---|
2670 | | - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
---|
2671 | | - usb3->reg = devm_ioremap_resource(&pdev->dev, res); |
---|
| 2770 | + usb3->reg = devm_platform_ioremap_resource(pdev, 0); |
---|
2672 | 2771 | if (IS_ERR(usb3->reg)) |
---|
2673 | 2772 | return PTR_ERR(usb3->reg); |
---|
2674 | 2773 | |
---|
.. | .. |
---|
2727 | 2826 | ret = device_create_file(&pdev->dev, &dev_attr_role); |
---|
2728 | 2827 | if (ret < 0) |
---|
2729 | 2828 | goto err_dev_create; |
---|
| 2829 | + |
---|
| 2830 | + if (device_property_read_bool(&pdev->dev, "usb-role-switch")) { |
---|
| 2831 | + usb3->role_sw_by_connector = true; |
---|
| 2832 | + renesas_usb3_role_switch_desc.fwnode = dev_fwnode(&pdev->dev); |
---|
| 2833 | + } |
---|
| 2834 | + |
---|
| 2835 | + renesas_usb3_role_switch_desc.driver_data = usb3; |
---|
2730 | 2836 | |
---|
2731 | 2837 | INIT_WORK(&usb3->role_work, renesas_usb3_role_work); |
---|
2732 | 2838 | usb3->role_sw = usb_role_switch_register(&pdev->dev, |
---|
.. | .. |
---|
2803 | 2909 | .probe = renesas_usb3_probe, |
---|
2804 | 2910 | .remove = renesas_usb3_remove, |
---|
2805 | 2911 | .driver = { |
---|
2806 | | - .name = (char *)udc_name, |
---|
| 2912 | + .name = udc_name, |
---|
2807 | 2913 | .pm = &renesas_usb3_pm_ops, |
---|
2808 | 2914 | .of_match_table = of_match_ptr(usb3_of_match), |
---|
2809 | 2915 | }, |
---|