linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v8 00/14] USB OTG/dual-role framework
@ 2016-05-13 10:03 Roger Quadros
  2016-05-13 10:03 ` [PATCH v8 01/14] usb: hcd: Initialize hcd->flags to 0 Roger Quadros
                   ` (14 more replies)
  0 siblings, 15 replies; 62+ messages in thread
From: Roger Quadros @ 2016-05-13 10:03 UTC (permalink / raw)
  To: peter.chen
  Cc: balbi, tony, gregkh, dan.j.williams, mathias.nyman, Joao.Pinto,
	sergei.shtylyov, jun.li, grygorii.strashko, yoshihiro.shimoda.uh,
	robh, nsekhar, b-liu, linux-usb, linux-omap, linux-kernel,
	devicetree, Roger Quadros

Hi,

This series centralizes OTG/Dual-role functionality in the kernel.
As of now I've got Dual-role functionality working pretty reliably on
dra7-evm and am437x-gp-evm.
NOTE: my am437x-gp-evm broke so I couldn't test v8 on it.
But the changes since v7 are trivial and shouldn't impact am437x-gp-evm.

DWC3 controller and platform related patches will be sent separately.

Series is based on v4.6-rc1 and depends on first 2 patches of [1]
[1] - OTG fsm cleanup - https://lkml.org/lkml/2016/3/30/186

Why?:
----

Currently there is no central location where OTG/dual-role functionality is
implemented in the Linux USB stack and every USB controller driver is
doing their own thing for OTG/dual-role. We can benefit from code-reuse
and simplicity by adding the OTG/dual-role core driver.

Newer OTG cores support standard host interface (e.g. xHCI) so
host and gadget functionality are no longer closely knit like older
cores. There needs to be a way to co-ordinate the operation of the
host and gadget controllers in dual-role mode. i.e. to stop and start them
from a central location. This central location should be the
USB OTG/dual-role core.

Host and gadget controllers might be sharing resources and can't
be always running. One has to be stopped for the other to run.
This couldn't be done till now but can be done from the OTG core.

What?:
-----

The OTG/dual-role core consists of a set of APIs that allow
registration of OTG controller device and OTG capable host and gadget
controllers.

- The OTG controller driver can provide the OTG capabilities and the
Finite State Machine work function via 'struct usb_otg_config'
at the time of registration i.e. usb_otg_register();

	struct usb_otg *usb_otg_register(struct device *dev,
        	                         struct usb_otg_config *config);
	int usb_otg_unregister(struct device *dev);
	/**
	 * struct usb_otg_config - otg controller configuration
	 * @caps: otg capabilities of the controller
	 * @ops: otg fsm operations
	 * @otg_work: optional custom otg state machine work function
	 */
	struct usb_otg_config {
	        struct usb_otg_caps *otg_caps;
	        struct otg_fsm_ops *fsm_ops;
	        void (*otg_work)(struct work_struct *work);
	};

The dual-role state machine is built-into the OTG core so nothing
special needs to be provided if only dual-role functionality is desired.
The low level OTG controller driver ops are povided via
'struct otg_fsm_ops *fsm_ops' in the 'struct usb_otg_config'.

After registration, the OTG core waits for host, gadget controller
and the gadget function driver to be registered. Once all resources are
available it instantiates the Finite State Machine (FSM).
The host/gadget controllers are started/stopped according to the FSM.

- Host and gadget controllers that are a part of OTG/dual-role port must
use the OTG core provided APIs to add/remove the host/gadget.
i.e. hosts must use usb_otg_add_hcd() usb_otg_remove_hcd(),,
gadgets must use usb_otg_add_gadget_udc() usb_del_gadget_udc().
This ensures that the host and gadget controllers are not started till
the state machine is ready and the right bus conditions are met.
It also allows the host and gadget controllers to provide the OTG
controller device to link them together. For Device tree boots
the related OTG controller is automatically picked up via the
'otg-controller' property in the Host/Gadget controller nodes.

	int usb_otg_add_hcd(struct usb_hcd *hcd,
			    unsigned int irqnum, unsigned long irqflags,
			    struct device *otg_dev);
	void usb_otg_remove_hcd(struct usb_hcd *hcd);

	int usb_otg_add_gadget_udc(struct device *parent,
				   struct usb_gadget *gadget,
				   struct device *otg_dev);
	usb_del_gadget_udc() must be used for removal.


- During the lifetime of the FSM, the OTG controller driver can provide
inputs event changes using usb_otg_sync_inputs(). The OTG core will
then schedule the FSM work function (or internal dual-role state machine)
to update the FSM state. The FSM then calls the OTG controller
operations (fsm_ops) as necessary.
	void usb_otg_sync_inputs(struct usb_otg *otg);

- The following 2 functions are provided as helpers for use by the
OTG controller driver to start/stop the host/gadget controllers.
	int usb_otg_start_host(struct usb_otg *otg, int on);
	int usb_otg_start_gadget(struct usb_otg *otg, int on);

- The following function is provided for use by the USB host stack
to sync OTG related events to the OTG state machine.
e.g. change in host_bus->b_hnp_enable, gadget->b_hnp_enable
	int usb_otg_kick_fsm(struct device *otg_device);

Changelog:
---------
v8:
- split out start/stop gadget and connect/disconnect operations.
- make CONFIG_OTG dpend on CONFIG_USB_GADGET as well apart from CONFIG_USB
- use create_freezable_workqueue() for OTG work as per Peter's suggestion.
- remove usb-otg.h as we're not initializing any OTG timers.
- don't include unnecessary headers in usb-otg.c (i.e. hrtimer.h & ktime.h)

v7:
- added dual-role support for host controllers requiring a companion
controller. e.g. EHCI + OHCI.
- added of_usb_get_otg() to get the OTG controller device
from the USB controller's device node.
- addressed review comments.

v6:
- added otg specific APIs for host/gadget registration. behaviour of
original host/gadget API remains unchanged. Platform devices can now
pass the otg device explicitly while registering host/gadget.
- moved hcd specific operations from struct otg_fsm to struct hcd_ops.
- made struct usb_otg mandatory for all otg related APIs.
- allow otg controller to provide it's own otg_work function so that
it can implement it's own state machine.
- removed otg fsm and timers from usb-otg.c. Only dual-role state machine
is implemented.
- vbus is controlled in the dual-role state machine.
- PM runtime is used around drd_statemachine().
- added otg_dev to xhci platform data to allow platform code to specify
the otg controller tied to the xhci host controller.

v5: Internal version. Not sent to mailing list

v4:
- Added DT support for tying otg-controller to host and gadget
 controllers. For DT we no longer have the constraint that
 OTG controller needs to be parent of host and gadget. They can be
 tied together using the "otg-controller" property.
- Relax the requirement for DT case that otg controller must register
 before host/gadget. We maintain a wait list of host/gadget devices
 waiting on the otg controller.
- Use a single struct usb_otg for otg data.
- Don't override host/gadget start/stop APIs. Let the controller
 drivers do what they want as they know best. Helper API is provided
 for controller start/stop that controller driver can use.
- Introduce struct usb_otg_config to pass the otg capabilities,
 otg ops and otg timer timeouts during otg controller registration.
- rebased on Greg's usb.git/usb-next

v3:
- all otg related definations now in otg.h
- single kernel config USB_OTG to enable OTG core and FSM.
- resolved symbol dependency issues.
- use dev_vdbg instead of VDBG() in usb-otg-fsm.c
- rebased on v4.2-rc1

v2:
- Use add/remove_hcd() instead of start/stop_hcd() to enable/disable
 the host controller
- added dual-role-device (DRD) state machine which is a much simpler
 mode of operation when compared to OTG. Here we don't support fancy
 OTG features like HNP, SRP, on the fly role-swap. The mode of operation
 is determined based on ID pin (cable type) and the role doesn't change
 till the cable type changes.

--
cheers,
-roger

Roger Quadros (13):
  usb: hcd: Initialize hcd->flags to 0
  usb: otg-fsm: Prevent build warning "VDBG" redefined
  usb: hcd.h: Add OTG to HCD interface
  usb: otg-fsm: use usb_otg wherever possible
  usb: otg-fsm: move host controller operations into usb_otg->hcd_ops
  usb: gadget.h: Add OTG to gadget interface
  usb: otg: get rid of CONFIG_USB_OTG_FSM in favour of CONFIG_USB_OTG
  usb: otg: add OTG/dual-role core
  usb: of: add an API to get OTG device from USB controller node
  usb: otg: use dev_dbg() instead of VDBG()
  usb: hcd: Adapt to OTG core
  usb: gadget: udc: adapt to OTG core
  usb: host: xhci-plat: Add otg device to platform data

Yoshihiro Shimoda (1):
  usb: otg: add hcd companion support

 Documentation/devicetree/bindings/usb/generic.txt |    6 +
 Documentation/usb/chipidea.txt                    |    2 +-
 drivers/usb/chipidea/Makefile                     |    2 +-
 drivers/usb/chipidea/ci.h                         |    3 +-
 drivers/usb/chipidea/core.c                       |   14 +-
 drivers/usb/chipidea/debug.c                      |    2 +-
 drivers/usb/chipidea/otg_fsm.c                    |  176 ++--
 drivers/usb/chipidea/otg_fsm.h                    |    2 +-
 drivers/usb/chipidea/udc.c                        |   17 +-
 drivers/usb/common/Makefile                       |    3 +-
 drivers/usb/common/common.c                       |   27 +
 drivers/usb/common/usb-otg-fsm.c                  |  203 ++--
 drivers/usb/common/usb-otg.c                      | 1056 +++++++++++++++++++++
 drivers/usb/core/Kconfig                          |   12 +-
 drivers/usb/core/hcd.c                            |   56 ++
 drivers/usb/gadget/udc/udc-core.c                 |  194 +++-
 drivers/usb/host/xhci-plat.c                      |   35 +-
 drivers/usb/phy/Kconfig                           |    2 +-
 drivers/usb/phy/phy-fsl-usb.c                     |  155 +--
 drivers/usb/phy/phy-fsl-usb.h                     |    3 +-
 include/linux/usb/gadget.h                        |   22 +
 include/linux/usb/hcd.h                           |   29 +
 include/linux/usb/of.h                            |    9 +
 include/linux/usb/otg-fsm.h                       |  154 +--
 include/linux/usb/otg.h                           |  264 +++++-
 include/linux/usb/xhci_pdriver.h                  |    3 +
 26 files changed, 2013 insertions(+), 438 deletions(-)
 create mode 100644 drivers/usb/common/usb-otg.c

-- 
2.7.4

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [PATCH v8 01/14] usb: hcd: Initialize hcd->flags to 0
  2016-05-13 10:03 [PATCH v8 00/14] USB OTG/dual-role framework Roger Quadros
@ 2016-05-13 10:03 ` Roger Quadros
  2016-05-13 10:03 ` [PATCH v8 02/14] usb: otg-fsm: Prevent build warning "VDBG" redefined Roger Quadros
                   ` (13 subsequent siblings)
  14 siblings, 0 replies; 62+ messages in thread
From: Roger Quadros @ 2016-05-13 10:03 UTC (permalink / raw)
  To: peter.chen
  Cc: balbi, tony, gregkh, dan.j.williams, mathias.nyman, Joao.Pinto,
	sergei.shtylyov, jun.li, grygorii.strashko, yoshihiro.shimoda.uh,
	robh, nsekhar, b-liu, linux-usb, linux-omap, linux-kernel,
	devicetree, Roger Quadros

When using the OTG/drd library we can call hcd_add/remove
consecutively without calling usb_put_hcd/usb_create_hcd in between
so hcd->flags can be stale.

If the HC dies due to whatever reason then without this
patch we get the below error on next hcd_add.

[   91.494257] xhci-hcd xhci-hcd.0.auto: HC died; cleaning up
[   91.502068] hub 3-0:1.0: state 0 ports 1 chg 0000 evt 0000
[   91.510240] xhci-hcd xhci-hcd.0.auto: xHCI Host Controller
[   91.516940] xhci-hcd xhci-hcd.0.auto: new USB bus registered, assigned bus number 4
[   91.529745] usb usb4: We don't know the algorithms for LPM for this host, disabling LPM.
[   91.540637] usb usb4: New USB device found, idVendor=1d6b, idProduct=0003
[   91.757865] irq 254: nobody cared (try booting with the "irqpoll" option)
[   91.757880] CPU: 0 PID: 68 Comm: kworker/u2:2 Not tainted 4.1.4-00828-g1f0ed8c-dirty #44
[   91.757885] Hardware name: Generic AM43 (Flattened Device Tree)
[   91.757914] Workqueue: usb_otg usb_otg_work
[   91.757921] Backtrace:
[   91.757954] [<c0012af0>] (dump_backtrace) from [<c0012c8c>] (show_stack+0x18/0x1c)
[   91.757972]  r6:c089d4a4 r5:ffffffff r4:00000000 r3:ee440000
[   91.757991] [<c0012c74>] (show_stack) from [<c05f7c14>] (dump_stack+0x84/0xd0)
[   91.758008] [<c05f7b90>] (dump_stack) from [<c0084b30>] (__report_bad_irq+0x28/0xc8)
[   91.758024]  r7:00000000 r6:000000fe r5:00000000 r4:ee514c40
[   91.758037] [<c0084b08>] (__report_bad_irq) from [<c00850b0>] (note_interrupt+0x24c/0x2ac)
[   91.758052]  r6:000000fe r5:00000000 r4:ee514c40 r3:00000000
[   91.758065] [<c0084e64>] (note_interrupt) from [<c00828fc>] (handle_irq_event_percpu+0xb0/0x158)
[   91.758085]  r10:ee514c40 r9:c08ce49a r8:000000fe r7:00000000 r6:00000000 r5:00000000
[   91.758094]  r4:00000000 r3:00000000
[   91.758105] [<c008284c>] (handle_irq_event_percpu) from [<c00829e8>] (handle_irq_event+0x44/0x64)
[   91.758126]  r10:00000001 r9:ee441ab0 r8:ee441bb8 r7:c0858b4c r6:ed174280 r5:ee514ca0
[   91.758132]  r4:ee514c40
[   91.758144] [<c00829a4>] (handle_irq_event) from [<c0085970>] (handle_fasteoi_irq+0x100/0x1bc)
[   91.758159]  r6:c085dba0 r5:ee514ca0 r4:ee514c40 r3:00000000
[   91.758171] [<c0085870>] (handle_fasteoi_irq) from [<c0082058>] (generic_handle_irq+0x28/0x38)
[   91.758186]  r7:c0853d40 r6:c0858b4c r5:000000fe r4:000000fe
[   91.758197] [<c0082030>] (generic_handle_irq) from [<c00821c0>] (__handle_domain_irq+0x98/0x12c)
[   91.758207]  r4:c0853d40 r3:00000100
[   91.758219] [<c0082128>] (__handle_domain_irq) from [<c00094e0>] (gic_handle_irq+0x28/0x68)
[   91.758239]  r10:00000001 r9:ee441bb8 r8:fa240100 r7:c0858d70 r6:ee441ab0 r5:000000b8
[   91.758245]  r4:fa24010c
[   91.758264] [<c00094b8>] (gic_handle_irq) from [<c05fd540>] (__irq_svc+0x40/0x74)
[   91.758271] Exception stack(0xee441ab0 to 0xee441af8)
[   91.758280] 1aa0:                                     00000000 c08d2980 ee441ac0 00000000
[   91.758292] 1ac0: 00000008 00000089 c0858b4c c0858080 00000000 ee441bb8 00000001 ee441b3c
[   91.758301] 1ae0: 00000101 ee441af8 c02fc418 c0046a1c 20000113 ffffffff
[   91.758321]  r8:00000000 r7:ee441ae4 r6:ffffffff r5:20000113 r4:c0046a1c r3:c02fc418
[   91.758347] [<c00469a0>] (__do_softirq) from [<c0046eac>] (irq_exit+0xb8/0x104)
[   91.758367]  r10:00000001 r9:ee441bb8 r8:00000000 r7:c0853d40 r6:c0858b4c r5:00000089
[   91.758373]  r4:00000000
[   91.758386] [<c0046df4>] (irq_exit) from [<c00821c8>] (__handle_domain_irq+0xa0/0x12c)
[   91.758395]  r4:00000000 r3:00000100
[   91.758406] [<c0082128>] (__handle_domain_irq) from [<c00094e0>] (gic_handle_irq+0x28/0x68)
[   91.758426]  r10:c08e3510 r9:20000013 r8:fa240100 r7:c0858d70 r6:ee441bb8 r5:00000039
[   91.758433]  r4:fa24010c
[   91.758445] [<c00094b8>] (gic_handle_irq) from [<c05fd540>] (__irq_svc+0x40/0x74)
[   91.758450] Exception stack(0xee441bb8 to 0xee441c00)
[   91.758457] 1ba0:                                                       00000000 00000001
[   91.758468] 1bc0: 00000000 ee440000 c08e2524 0000004d 00000274 00000000 00000000 20000013
[   91.758479] 1be0: c08e3510 ee441c4c ee441b60 ee441c00 c03acfec c0080d4c 60000013 ffffffff
[   91.758499]  r8:00000000 r7:ee441bec r6:ffffffff r5:60000013 r4:c0080d4c r3:c03acfec
[   91.758524] [<c0080950>] (console_unlock) from [<c0081670>] (vprintk_emit+0x20c/0x500)
[   91.758544]  r10:ee441cc0 r9:c08d3550 r8:c08e3ea0 r7:00000000 r6:00000001 r5:0000003d
[   91.758551]  r4:c08d3550
[   91.758573] [<c0081464>] (vprintk_emit) from [<c03f6f70>] (dev_vprintk_emit+0x104/0x1ac)
[   91.758593]  r10:ee441d8c r9:0000000e r8:c07951e0 r7:00000006 r6:ee441cc0 r5:0000000d
[   91.758599]  r4:ee731068
[   91.758612] [<c03f6e6c>] (dev_vprintk_emit) from [<c03f7040>] (dev_printk_emit+0x28/0x30)
[   91.758632]  r10:00000001 r9:ee5f8410 r8:ee731000 r7:ed429000 r6:00000006 r5:ee441dc0
[   91.758638]  r4:ee731068
[   91.758651] [<c03f701c>] (dev_printk_emit) from [<c03f7098>] (__dev_printk+0x50/0x70)
[   91.758660]  r3:bf2268cc r2:c07951e0
[   91.758673] [<c03f7048>] (__dev_printk) from [<c03f70f4>] (_dev_info+0x3c/0x48)
[   91.758686]  r6:00000000 r5:ee731068 r4:ee731000
[   91.758790] [<c03f70bc>] (_dev_info) from [<bf20ec3c>] (usb_new_device+0x11c/0x518 [usbcore])
[   91.758804]  r3:00000003 r2:00001d6b r1:bf225bc4
[   91.758881] [<bf20eb20>] (usb_new_device [usbcore]) from [<bf213560>] (usb_otg_add_hcd+0x514/0x7f8 [usbcore])
[   91.758903]  r10:00000001 r9:ee5f8410 r8:ee731000 r7:000000fe r6:ed4290c8 r5:00000000
[   91.758909]  r4:ed429000
[   91.758957] [<bf21304c>] (usb_otg_add_hcd [usbcore]) from [<c047a238>] (usb_otg_start_host+0xb8/0xf8)
[   91.758978]  r10:00000000 r9:00000002 r8:00000000 r7:ee02b000 r6:ee452808 r5:ee452808
[   91.758985]  r4:ee452808
[   91.758997] [<c047a180>] (usb_otg_start_host) from [<c047a020>] (drd_set_protocol+0xac/0xd8)
[   91.759007]  r4:00000001 r3:c047a180
[   91.759018] [<c0479f74>] (drd_set_protocol) from [<c047a2ec>] (drd_set_state+0x74/0x98)
[   91.759027]  r5:ee452808 r4:00000009
[   91.759039] [<c047a278>] (drd_set_state) from [<c047a3dc>] (usb_otg_work+0xcc/0x154)
[   91.759054]  r6:ee452808 r5:ee4528b8 r4:ee452968 r3:00000000
[   91.759072] [<c047a310>] (usb_otg_work) from [<c005754c>] (process_one_work+0x128/0x340)
[   91.759087]  r6:ee02ac00 r5:ee452968 r4:ee42b900 r3:c047a310
[   91.759100] [<c0057424>] (process_one_work) from [<c00578f8>] (worker_thread+0x158/0x49c)
[   91.759120]  r10:ee42b900 r9:00000002 r8:ee02ac00 r7:00000088 r6:ee42b918 r5:ee02ac00
[   91.759127]  r4:ee02ac14
[   91.759145] [<c00577a0>] (worker_thread) from [<c005cc40>] (kthread+0xdc/0xf8)
[   91.759165]  r10:00000000 r9:00000000 r8:00000000 r7:c00577a0 r6:ee42b900 r5:ee429940
[   91.759174]  r4:00000000 r3:00000000
[   91.759190] [<c005cb64>] (kthread) from [<c000fc08>] (ret_from_fork+0x14/0x2c)
[   91.759206]  r7:00000000 r6:00000000 r5:c005cb64 r4:ee429940
[   91.759209] handlers:
[   91.759255] [<bf211b5c>] usb_hcd_irq [usbcore]
[   91.759260] Disabling IRQ #254

Signed-off-by: Roger Quadros <rogerq@ti.com>
Reviewed-by: Peter Chen <peter.chen@nxp.com>
---
 drivers/usb/core/hcd.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index 2ca2cef..9484539 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -3009,6 +3009,7 @@ void usb_remove_hcd(struct usb_hcd *hcd)
 	}
 
 	usb_put_invalidate_rhdev(hcd);
+	hcd->flags = 0;
 }
 EXPORT_SYMBOL_GPL(usb_remove_hcd);
 
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH v8 02/14] usb: otg-fsm: Prevent build warning "VDBG" redefined
  2016-05-13 10:03 [PATCH v8 00/14] USB OTG/dual-role framework Roger Quadros
  2016-05-13 10:03 ` [PATCH v8 01/14] usb: hcd: Initialize hcd->flags to 0 Roger Quadros
@ 2016-05-13 10:03 ` Roger Quadros
  2016-05-13 10:03 ` [PATCH v8 03/14] usb: hcd.h: Add OTG to HCD interface Roger Quadros
                   ` (12 subsequent siblings)
  14 siblings, 0 replies; 62+ messages in thread
From: Roger Quadros @ 2016-05-13 10:03 UTC (permalink / raw)
  To: peter.chen
  Cc: balbi, tony, gregkh, dan.j.williams, mathias.nyman, Joao.Pinto,
	sergei.shtylyov, jun.li, grygorii.strashko, yoshihiro.shimoda.uh,
	robh, nsekhar, b-liu, linux-usb, linux-omap, linux-kernel,
	devicetree, Roger Quadros

If usb/otg-fsm.h and usb/composite.h are included together
then it results in the build warning [1].

Prevent that by defining VDBG locally.

Also get rid of MPC_LOC which doesn't seem to be used
by anyone.

[1] - warning fixed by this patch:

In file included from drivers/usb/dwc3/core.h:33,
   from drivers/usb/dwc3/ep0.c:33:
   include/linux/usb/otg-fsm.h:30:1: warning: "VDBG" redefined
   In file included from drivers/usb/dwc3/ep0.c:31:
   include/linux/usb/composite.h:615:1: warning: this is the location
   of the previous definition

Signed-off-by: Roger Quadros <rogerq@ti.com>
Acked-by: Peter Chen <peter.chen@nxp.com>
---
 drivers/usb/common/usb-otg-fsm.c |  7 +++++++
 drivers/usb/phy/phy-fsl-usb.c    |  7 +++++++
 include/linux/usb/otg-fsm.h      | 15 ---------------
 3 files changed, 14 insertions(+), 15 deletions(-)

diff --git a/drivers/usb/common/usb-otg-fsm.c b/drivers/usb/common/usb-otg-fsm.c
index 9059b7d..015cf41 100644
--- a/drivers/usb/common/usb-otg-fsm.c
+++ b/drivers/usb/common/usb-otg-fsm.c
@@ -30,6 +30,13 @@
 #include <linux/usb/otg.h>
 #include <linux/usb/otg-fsm.h>
 
+#ifdef VERBOSE
+#define VDBG(fmt, args...) pr_debug("[%s]  " fmt , \
+				 __func__, ## args)
+#else
+#define VDBG(stuff...)	do {} while (0)
+#endif
+
 /* Change USB protocol when there is a protocol change */
 static int otg_set_protocol(struct otg_fsm *fsm, int protocol)
 {
diff --git a/drivers/usb/phy/phy-fsl-usb.c b/drivers/usb/phy/phy-fsl-usb.c
index 94eb292..dd8a1ad 100644
--- a/drivers/usb/phy/phy-fsl-usb.c
+++ b/drivers/usb/phy/phy-fsl-usb.c
@@ -44,6 +44,13 @@
 
 #include "phy-fsl-usb.h"
 
+#ifdef VERBOSE
+#define VDBG(fmt, args...) pr_debug("[%s]  " fmt , \
+				 __func__, ## args)
+#else
+#define VDBG(stuff...)	do {} while (0)
+#endif
+
 #define DRIVER_VERSION "Rev. 1.55"
 #define DRIVER_AUTHOR "Jerry Huang/Li Yang"
 #define DRIVER_DESC "Freescale USB OTG Transceiver Driver"
diff --git a/include/linux/usb/otg-fsm.h b/include/linux/usb/otg-fsm.h
index 7a03505..a0a8f87 100644
--- a/include/linux/usb/otg-fsm.h
+++ b/include/linux/usb/otg-fsm.h
@@ -21,21 +21,6 @@
 #include <linux/mutex.h>
 #include <linux/errno.h>
 
-#undef VERBOSE
-
-#ifdef VERBOSE
-#define VDBG(fmt, args...) pr_debug("[%s]  " fmt , \
-				 __func__, ## args)
-#else
-#define VDBG(stuff...)	do {} while (0)
-#endif
-
-#ifdef VERBOSE
-#define MPC_LOC printk("Current Location [%s]:[%d]\n", __FILE__, __LINE__)
-#else
-#define MPC_LOC do {} while (0)
-#endif
-
 #define PROTO_UNDEF	(0)
 #define PROTO_HOST	(1)
 #define PROTO_GADGET	(2)
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH v8 03/14] usb: hcd.h: Add OTG to HCD interface
  2016-05-13 10:03 [PATCH v8 00/14] USB OTG/dual-role framework Roger Quadros
  2016-05-13 10:03 ` [PATCH v8 01/14] usb: hcd: Initialize hcd->flags to 0 Roger Quadros
  2016-05-13 10:03 ` [PATCH v8 02/14] usb: otg-fsm: Prevent build warning "VDBG" redefined Roger Quadros
@ 2016-05-13 10:03 ` Roger Quadros
  2016-05-13 10:03 ` [PATCH v8 04/14] usb: otg-fsm: use usb_otg wherever possible Roger Quadros
                   ` (11 subsequent siblings)
  14 siblings, 0 replies; 62+ messages in thread
From: Roger Quadros @ 2016-05-13 10:03 UTC (permalink / raw)
  To: peter.chen
  Cc: balbi, tony, gregkh, dan.j.williams, mathias.nyman, Joao.Pinto,
	sergei.shtylyov, jun.li, grygorii.strashko, yoshihiro.shimoda.uh,
	robh, nsekhar, b-liu, linux-usb, linux-omap, linux-kernel,
	devicetree, Roger Quadros

The OTG core will use struct otg_hcd_ops to interface
with the HCD controller.

The main purpose of this interface is to avoid directly
calling HCD APIs from the OTG core as they
wouldn't be defined in the built-in symbol table if
CONFIG_USB is m.

Signed-off-by: Roger Quadros <rogerq@ti.com>
Acked-by: Peter Chen <peter.chen@nxp.com>
---
 include/linux/usb/hcd.h | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h
index b98f831..861ccaa 100644
--- a/include/linux/usb/hcd.h
+++ b/include/linux/usb/hcd.h
@@ -399,6 +399,30 @@ struct hc_driver {
 
 };
 
+/**
+ * struct otg_hcd_ops - Interface between OTG core and HCD
+ *
+ * Provided by the HCD core to allow the OTG core to interface with the HCD
+ *
+ * @add: function to add the HCD
+ * @remove: function to remove the HCD
+ * @usb_bus_start_enum: function to immediately start bus enumeration
+ * @usb_control_msg: function to build and send of a control urb
+ * @usb_hub_find_child: function to get pointer to the child device
+ */
+struct otg_hcd_ops {
+	int (*add)(struct usb_hcd *hcd,
+		   unsigned int irqnum, unsigned long irqflags);
+	void (*remove)(struct usb_hcd *hcd);
+	int (*usb_bus_start_enum)(struct usb_bus *bus, unsigned int port_num);
+	int (*usb_control_msg)(struct usb_device *dev, unsigned int pipe,
+			       __u8 request, __u8 requesttype, __u16 value,
+			       __u16 index, void *data, __u16 size,
+			       int timeout);
+	struct usb_device * (*usb_hub_find_child)(struct usb_device *hdev,
+						  int port1);
+};
+
 static inline int hcd_giveback_urb_in_bh(struct usb_hcd *hcd)
 {
 	return hcd->driver->flags & HCD_BH;
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH v8 04/14] usb: otg-fsm: use usb_otg wherever possible
  2016-05-13 10:03 [PATCH v8 00/14] USB OTG/dual-role framework Roger Quadros
                   ` (2 preceding siblings ...)
  2016-05-13 10:03 ` [PATCH v8 03/14] usb: hcd.h: Add OTG to HCD interface Roger Quadros
@ 2016-05-13 10:03 ` Roger Quadros
  2016-05-13 10:03 ` [PATCH v8 05/14] usb: otg-fsm: move host controller operations into usb_otg->hcd_ops Roger Quadros
                   ` (10 subsequent siblings)
  14 siblings, 0 replies; 62+ messages in thread
From: Roger Quadros @ 2016-05-13 10:03 UTC (permalink / raw)
  To: peter.chen
  Cc: balbi, tony, gregkh, dan.j.williams, mathias.nyman, Joao.Pinto,
	sergei.shtylyov, jun.li, grygorii.strashko, yoshihiro.shimoda.uh,
	robh, nsekhar, b-liu, linux-usb, linux-omap, linux-kernel,
	devicetree, Roger Quadros

Move otg_fsm into usb_otg and use usb_otg wherever possible
in the usb_otg APIs.

Signed-off-by: Roger Quadros <rogerq@ti.com>
Acked-by: Peter Chen <peter.chen@nxp.com>
---
 drivers/usb/chipidea/ci.h        |   1 -
 drivers/usb/chipidea/core.c      |  14 +--
 drivers/usb/chipidea/debug.c     |   2 +-
 drivers/usb/chipidea/otg_fsm.c   | 169 ++++++++++++++++++------------------
 drivers/usb/chipidea/udc.c       |  17 ++--
 drivers/usb/common/usb-otg-fsm.c | 180 ++++++++++++++++++++-------------------
 drivers/usb/phy/phy-fsl-usb.c    | 141 +++++++++++++++---------------
 drivers/usb/phy/phy-fsl-usb.h    |   3 +-
 include/linux/usb/otg-fsm.h      | 132 +++-------------------------
 include/linux/usb/otg.h          | 107 +++++++++++++++++++++++
 10 files changed, 383 insertions(+), 383 deletions(-)

diff --git a/drivers/usb/chipidea/ci.h b/drivers/usb/chipidea/ci.h
index cd41455..c523975 100644
--- a/drivers/usb/chipidea/ci.h
+++ b/drivers/usb/chipidea/ci.h
@@ -209,7 +209,6 @@ struct ci_hdrc {
 	enum ci_role			role;
 	bool				is_otg;
 	struct usb_otg			otg;
-	struct otg_fsm			fsm;
 	struct hrtimer			otg_fsm_hrtimer;
 	ktime_t				hr_timeouts[NUM_OTG_FSM_TIMERS];
 	unsigned			enabled_otg_timer_bits;
diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c
index 69426e6..56b6ac6 100644
--- a/drivers/usb/chipidea/core.c
+++ b/drivers/usb/chipidea/core.c
@@ -1085,8 +1085,8 @@ static int ci_hdrc_remove(struct platform_device *pdev)
 /* Prepare wakeup by SRP before suspend */
 static void ci_otg_fsm_suspend_for_srp(struct ci_hdrc *ci)
 {
-	if ((ci->fsm.otg->state == OTG_STATE_A_IDLE) &&
-				!hw_read_otgsc(ci, OTGSC_ID)) {
+	if ((ci->otg.state == OTG_STATE_A_IDLE) &&
+	    !hw_read_otgsc(ci, OTGSC_ID)) {
 		hw_write(ci, OP_PORTSC, PORTSC_W1C_BITS | PORTSC_PP,
 								PORTSC_PP);
 		hw_write(ci, OP_PORTSC, PORTSC_W1C_BITS | PORTSC_WKCN,
@@ -1097,13 +1097,13 @@ static void ci_otg_fsm_suspend_for_srp(struct ci_hdrc *ci)
 /* Handle SRP when wakeup by data pulse */
 static void ci_otg_fsm_wakeup_by_srp(struct ci_hdrc *ci)
 {
-	if ((ci->fsm.otg->state == OTG_STATE_A_IDLE) &&
-		(ci->fsm.a_bus_drop == 1) && (ci->fsm.a_bus_req == 0)) {
+	if ((ci->otg.state == OTG_STATE_A_IDLE) &&
+	    (ci->otg.fsm.a_bus_drop == 1) && (ci->otg.fsm.a_bus_req == 0)) {
 		if (!hw_read_otgsc(ci, OTGSC_ID)) {
-			ci->fsm.a_srp_det = 1;
-			ci->fsm.a_bus_drop = 0;
+			ci->otg.fsm.a_srp_det = 1;
+			ci->otg.fsm.a_bus_drop = 0;
 		} else {
-			ci->fsm.id = 1;
+			ci->otg.fsm.id = 1;
 		}
 		ci_otg_queue_work(ci);
 	}
diff --git a/drivers/usb/chipidea/debug.c b/drivers/usb/chipidea/debug.c
index 6d23eed..374cdaa 100644
--- a/drivers/usb/chipidea/debug.c
+++ b/drivers/usb/chipidea/debug.c
@@ -224,7 +224,7 @@ static int ci_otg_show(struct seq_file *s, void *unused)
 	if (!ci || !ci_otg_is_fsm_mode(ci))
 		return 0;
 
-	fsm = &ci->fsm;
+	fsm = &ci->otg.fsm;
 
 	/* ------ State ----- */
 	seq_printf(s, "OTG state: %s\n\n",
diff --git a/drivers/usb/chipidea/otg_fsm.c b/drivers/usb/chipidea/otg_fsm.c
index de8e22e..1c0c750 100644
--- a/drivers/usb/chipidea/otg_fsm.c
+++ b/drivers/usb/chipidea/otg_fsm.c
@@ -40,7 +40,7 @@ get_a_bus_req(struct device *dev, struct device_attribute *attr, char *buf)
 
 	next = buf;
 	size = PAGE_SIZE;
-	t = scnprintf(next, size, "%d\n", ci->fsm.a_bus_req);
+	t = scnprintf(next, size, "%d\n", ci->otg.fsm.a_bus_req);
 	size -= t;
 	next += t;
 
@@ -56,25 +56,25 @@ set_a_bus_req(struct device *dev, struct device_attribute *attr,
 	if (count > 2)
 		return -1;
 
-	mutex_lock(&ci->fsm.lock);
+	mutex_lock(&ci->otg.fsm.lock);
 	if (buf[0] == '0') {
-		ci->fsm.a_bus_req = 0;
+		ci->otg.fsm.a_bus_req = 0;
 	} else if (buf[0] == '1') {
 		/* If a_bus_drop is TRUE, a_bus_req can't be set */
-		if (ci->fsm.a_bus_drop) {
-			mutex_unlock(&ci->fsm.lock);
+		if (ci->otg.fsm.a_bus_drop) {
+			mutex_unlock(&ci->otg.fsm.lock);
 			return count;
 		}
-		ci->fsm.a_bus_req = 1;
-		if (ci->fsm.otg->state == OTG_STATE_A_PERIPHERAL) {
+		ci->otg.fsm.a_bus_req = 1;
+		if (ci->otg.state == OTG_STATE_A_PERIPHERAL) {
 			ci->gadget.host_request_flag = 1;
-			mutex_unlock(&ci->fsm.lock);
+			mutex_unlock(&ci->otg.fsm.lock);
 			return count;
 		}
 	}
 
 	ci_otg_queue_work(ci);
-	mutex_unlock(&ci->fsm.lock);
+	mutex_unlock(&ci->otg.fsm.lock);
 
 	return count;
 }
@@ -89,7 +89,7 @@ get_a_bus_drop(struct device *dev, struct device_attribute *attr, char *buf)
 
 	next = buf;
 	size = PAGE_SIZE;
-	t = scnprintf(next, size, "%d\n", ci->fsm.a_bus_drop);
+	t = scnprintf(next, size, "%d\n", ci->otg.fsm.a_bus_drop);
 	size -= t;
 	next += t;
 
@@ -105,16 +105,16 @@ set_a_bus_drop(struct device *dev, struct device_attribute *attr,
 	if (count > 2)
 		return -1;
 
-	mutex_lock(&ci->fsm.lock);
+	mutex_lock(&ci->otg.fsm.lock);
 	if (buf[0] == '0') {
-		ci->fsm.a_bus_drop = 0;
+		ci->otg.fsm.a_bus_drop = 0;
 	} else if (buf[0] == '1') {
-		ci->fsm.a_bus_drop = 1;
-		ci->fsm.a_bus_req = 0;
+		ci->otg.fsm.a_bus_drop = 1;
+		ci->otg.fsm.a_bus_req = 0;
 	}
 
 	ci_otg_queue_work(ci);
-	mutex_unlock(&ci->fsm.lock);
+	mutex_unlock(&ci->otg.fsm.lock);
 
 	return count;
 }
@@ -130,7 +130,7 @@ get_b_bus_req(struct device *dev, struct device_attribute *attr, char *buf)
 
 	next = buf;
 	size = PAGE_SIZE;
-	t = scnprintf(next, size, "%d\n", ci->fsm.b_bus_req);
+	t = scnprintf(next, size, "%d\n", ci->otg.fsm.b_bus_req);
 	size -= t;
 	next += t;
 
@@ -146,20 +146,20 @@ set_b_bus_req(struct device *dev, struct device_attribute *attr,
 	if (count > 2)
 		return -1;
 
-	mutex_lock(&ci->fsm.lock);
+	mutex_lock(&ci->otg.fsm.lock);
 	if (buf[0] == '0')
-		ci->fsm.b_bus_req = 0;
+		ci->otg.fsm.b_bus_req = 0;
 	else if (buf[0] == '1') {
-		ci->fsm.b_bus_req = 1;
-		if (ci->fsm.otg->state == OTG_STATE_B_PERIPHERAL) {
+		ci->otg.fsm.b_bus_req = 1;
+		if (ci->otg.state == OTG_STATE_B_PERIPHERAL) {
 			ci->gadget.host_request_flag = 1;
-			mutex_unlock(&ci->fsm.lock);
+			mutex_unlock(&ci->otg.fsm.lock);
 			return count;
 		}
 	}
 
 	ci_otg_queue_work(ci);
-	mutex_unlock(&ci->fsm.lock);
+	mutex_unlock(&ci->otg.fsm.lock);
 
 	return count;
 }
@@ -174,12 +174,12 @@ set_a_clr_err(struct device *dev, struct device_attribute *attr,
 	if (count > 2)
 		return -1;
 
-	mutex_lock(&ci->fsm.lock);
+	mutex_lock(&ci->otg.fsm.lock);
 	if (buf[0] == '1')
-		ci->fsm.a_clr_err = 1;
+		ci->otg.fsm.a_clr_err = 1;
 
 	ci_otg_queue_work(ci);
-	mutex_unlock(&ci->fsm.lock);
+	mutex_unlock(&ci->otg.fsm.lock);
 
 	return count;
 }
@@ -287,64 +287,64 @@ static void ci_otg_del_timer(struct ci_hdrc *ci, enum otg_fsm_timer t)
 /* OTG FSM timer handlers */
 static int a_wait_vrise_tmout(struct ci_hdrc *ci)
 {
-	ci->fsm.a_wait_vrise_tmout = 1;
+	ci->otg.fsm.a_wait_vrise_tmout = 1;
 	return 0;
 }
 
 static int a_wait_vfall_tmout(struct ci_hdrc *ci)
 {
-	ci->fsm.a_wait_vfall_tmout = 1;
+	ci->otg.fsm.a_wait_vfall_tmout = 1;
 	return 0;
 }
 
 static int a_wait_bcon_tmout(struct ci_hdrc *ci)
 {
-	ci->fsm.a_wait_bcon_tmout = 1;
+	ci->otg.fsm.a_wait_bcon_tmout = 1;
 	return 0;
 }
 
 static int a_aidl_bdis_tmout(struct ci_hdrc *ci)
 {
-	ci->fsm.a_aidl_bdis_tmout = 1;
+	ci->otg.fsm.a_aidl_bdis_tmout = 1;
 	return 0;
 }
 
 static int b_ase0_brst_tmout(struct ci_hdrc *ci)
 {
-	ci->fsm.b_ase0_brst_tmout = 1;
+	ci->otg.fsm.b_ase0_brst_tmout = 1;
 	return 0;
 }
 
 static int a_bidl_adis_tmout(struct ci_hdrc *ci)
 {
-	ci->fsm.a_bidl_adis_tmout = 1;
+	ci->otg.fsm.a_bidl_adis_tmout = 1;
 	return 0;
 }
 
 static int b_aidl_bdis_tmout(struct ci_hdrc *ci)
 {
-	ci->fsm.a_bus_suspend = 1;
+	ci->otg.fsm.a_bus_suspend = 1;
 	return 0;
 }
 
 static int b_se0_srp_tmout(struct ci_hdrc *ci)
 {
-	ci->fsm.b_se0_srp = 1;
+	ci->otg.fsm.b_se0_srp = 1;
 	return 0;
 }
 
 static int b_srp_fail_tmout(struct ci_hdrc *ci)
 {
-	ci->fsm.b_srp_done = 1;
+	ci->otg.fsm.b_srp_done = 1;
 	return 1;
 }
 
 static int b_data_pls_tmout(struct ci_hdrc *ci)
 {
-	ci->fsm.b_srp_done = 1;
-	ci->fsm.b_bus_req = 0;
-	if (ci->fsm.power_up)
-		ci->fsm.power_up = 0;
+	ci->otg.fsm.b_srp_done = 1;
+	ci->otg.fsm.b_bus_req = 0;
+	if (ci->otg.fsm.power_up)
+		ci->otg.fsm.power_up = 0;
 	hw_write_otgsc(ci, OTGSC_HABA, 0);
 	pm_runtime_put(ci->dev);
 	return 0;
@@ -352,9 +352,9 @@ static int b_data_pls_tmout(struct ci_hdrc *ci)
 
 static int b_ssend_srp_tmout(struct ci_hdrc *ci)
 {
-	ci->fsm.b_ssend_srp = 1;
+	ci->otg.fsm.b_ssend_srp = 1;
 	/* only vbus fall below B_sess_vld in b_idle state */
-	if (ci->fsm.otg->state == OTG_STATE_B_IDLE)
+	if (ci->otg.state == OTG_STATE_B_IDLE)
 		return 0;
 	else
 		return 1;
@@ -435,18 +435,18 @@ static int ci_otg_init_timers(struct ci_hdrc *ci)
 /* -------------------------------------------------------------*/
 /* Operations that will be called from OTG Finite State Machine */
 /* -------------------------------------------------------------*/
-static void ci_otg_fsm_add_timer(struct otg_fsm *fsm, enum otg_fsm_timer t)
+static void ci_otg_fsm_add_timer(struct usb_otg *otg, enum otg_fsm_timer t)
 {
-	struct ci_hdrc	*ci = container_of(fsm, struct ci_hdrc, fsm);
+	struct ci_hdrc	*ci = container_of(otg, struct ci_hdrc, otg);
 
 	if (t < NUM_OTG_FSM_TIMERS)
 		ci_otg_add_timer(ci, t);
 	return;
 }
 
-static void ci_otg_fsm_del_timer(struct otg_fsm *fsm, enum otg_fsm_timer t)
+static void ci_otg_fsm_del_timer(struct usb_otg *otg, enum otg_fsm_timer t)
 {
-	struct ci_hdrc	*ci = container_of(fsm, struct ci_hdrc, fsm);
+	struct ci_hdrc	*ci = container_of(otg, struct ci_hdrc, otg);
 
 	if (t < NUM_OTG_FSM_TIMERS)
 		ci_otg_del_timer(ci, t);
@@ -457,10 +457,10 @@ static void ci_otg_fsm_del_timer(struct otg_fsm *fsm, enum otg_fsm_timer t)
  * A-device drive vbus: turn on vbus regulator and enable port power
  * Data pulse irq should be disabled while vbus is on.
  */
-static void ci_otg_drv_vbus(struct otg_fsm *fsm, int on)
+static void ci_otg_drv_vbus(struct usb_otg *otg, int on)
 {
 	int ret;
-	struct ci_hdrc	*ci = container_of(fsm, struct ci_hdrc, fsm);
+	struct ci_hdrc	*ci = container_of(otg, struct ci_hdrc, otg);
 
 	if (on) {
 		/* Enable power power */
@@ -478,23 +478,23 @@ static void ci_otg_drv_vbus(struct otg_fsm *fsm, int on)
 		/* Disable data pulse irq */
 		hw_write_otgsc(ci, OTGSC_DPIE, 0);
 
-		fsm->a_srp_det = 0;
-		fsm->power_up = 0;
+		otg->fsm.a_srp_det = 0;
+		otg->fsm.power_up = 0;
 	} else {
 		if (ci->platdata->reg_vbus)
 			regulator_disable(ci->platdata->reg_vbus);
 
-		fsm->a_bus_drop = 1;
-		fsm->a_bus_req = 0;
+		otg->fsm.a_bus_drop = 1;
+		otg->fsm.a_bus_req = 0;
 	}
 }
 
 /*
  * Control data line by Run Stop bit.
  */
-static void ci_otg_loc_conn(struct otg_fsm *fsm, int on)
+static void ci_otg_loc_conn(struct usb_otg *otg, int on)
 {
-	struct ci_hdrc	*ci = container_of(fsm, struct ci_hdrc, fsm);
+	struct ci_hdrc	*ci = container_of(otg, struct ci_hdrc, otg);
 
 	if (on)
 		hw_write(ci, OP_USBCMD, USBCMD_RS, USBCMD_RS);
@@ -511,14 +511,14 @@ static void ci_otg_loc_conn(struct otg_fsm *fsm, int on)
  * so the usb device class driver need support autosuspend,
  * otherwise the bus suspend will not happen.
  */
-static void ci_otg_loc_sof(struct otg_fsm *fsm, int on)
+static void ci_otg_loc_sof(struct usb_otg *otg, int on)
 {
 	struct usb_device *udev;
 
-	if (!fsm->otg->host)
+	if (!otg->host)
 		return;
 
-	udev = usb_hub_find_child(fsm->otg->host->root_hub, 1);
+	udev = usb_hub_find_child(otg->host->root_hub, 1);
 	if (!udev)
 		return;
 
@@ -534,9 +534,9 @@ static void ci_otg_loc_sof(struct otg_fsm *fsm, int on)
  * Start SRP pulsing by data-line pulsing,
  * no v-bus pulsing followed
  */
-static void ci_otg_start_pulse(struct otg_fsm *fsm)
+static void ci_otg_start_pulse(struct usb_otg *otg)
 {
-	struct ci_hdrc	*ci = container_of(fsm, struct ci_hdrc, fsm);
+	struct ci_hdrc	*ci = container_of(otg, struct ci_hdrc, otg);
 
 	/* Hardware Assistant Data pulse */
 	hw_write_otgsc(ci, OTGSC_HADP, OTGSC_HADP);
@@ -545,9 +545,9 @@ static void ci_otg_start_pulse(struct otg_fsm *fsm)
 	ci_otg_add_timer(ci, B_DATA_PLS);
 }
 
-static int ci_otg_start_host(struct otg_fsm *fsm, int on)
+static int ci_otg_start_host(struct usb_otg *otg, int on)
 {
-	struct ci_hdrc	*ci = container_of(fsm, struct ci_hdrc, fsm);
+	struct ci_hdrc	*ci = container_of(otg, struct ci_hdrc, otg);
 
 	if (on) {
 		ci_role_stop(ci);
@@ -559,9 +559,9 @@ static int ci_otg_start_host(struct otg_fsm *fsm, int on)
 	return 0;
 }
 
-static int ci_otg_start_gadget(struct otg_fsm *fsm, int on)
+static int ci_otg_start_gadget(struct usb_otg *otg, int on)
 {
-	struct ci_hdrc	*ci = container_of(fsm, struct ci_hdrc, fsm);
+	struct ci_hdrc	*ci = container_of(otg, struct ci_hdrc, otg);
 
 	if (on)
 		usb_gadget_vbus_connect(&ci->gadget);
@@ -588,13 +588,13 @@ int ci_otg_fsm_work(struct ci_hdrc *ci)
 	 * Don't do fsm transition for B device
 	 * when there is no gadget class driver
 	 */
-	if (ci->fsm.id && !(ci->driver) &&
-		ci->fsm.otg->state < OTG_STATE_A_IDLE)
+	if (ci->otg.fsm.id && !(ci->driver) &&
+	    ci->otg.state < OTG_STATE_A_IDLE)
 		return 0;
 
 	pm_runtime_get_sync(ci->dev);
-	if (otg_statemachine(&ci->fsm)) {
-		if (ci->fsm.otg->state == OTG_STATE_A_IDLE) {
+	if (otg_statemachine(&ci->otg)) {
+		if (ci->otg.state == OTG_STATE_A_IDLE) {
 			/*
 			 * Further state change for cases:
 			 * a_idle to b_idle; or
@@ -603,8 +603,8 @@ int ci_otg_fsm_work(struct ci_hdrc *ci)
 			 * consequently; or
 			 * a_idle to a_wait_vrise when power up
 			 */
-			if ((ci->fsm.id) || (ci->id_event) ||
-						(ci->fsm.power_up)) {
+			if ((ci->otg.fsm.id) || (ci->id_event) ||
+			    (ci->otg.fsm.power_up)) {
 				ci_otg_queue_work(ci);
 			} else {
 				/* Enable data pulse irq */
@@ -615,16 +615,16 @@ int ci_otg_fsm_work(struct ci_hdrc *ci)
 			}
 			if (ci->id_event)
 				ci->id_event = false;
-		} else if (ci->fsm.otg->state == OTG_STATE_B_IDLE) {
-			if (ci->fsm.b_sess_vld) {
-				ci->fsm.power_up = 0;
+		} else if (ci->otg.state == OTG_STATE_B_IDLE) {
+			if (ci->otg.fsm.b_sess_vld) {
+				ci->otg.fsm.power_up = 0;
 				/*
 				 * Further transite to b_periphearl state
 				 * when register gadget driver with vbus on
 				 */
 				ci_otg_queue_work(ci);
 			}
-		} else if (ci->fsm.otg->state == OTG_STATE_A_HOST) {
+		} else if (ci->otg.state == OTG_STATE_A_HOST) {
 			pm_runtime_mark_last_busy(ci->dev);
 			pm_runtime_put_autosuspend(ci->dev);
 			return 0;
@@ -641,13 +641,13 @@ int ci_otg_fsm_work(struct ci_hdrc *ci)
 static void ci_otg_fsm_event(struct ci_hdrc *ci)
 {
 	u32 intr_sts, otg_bsess_vld, port_conn;
-	struct otg_fsm *fsm = &ci->fsm;
+	struct otg_fsm *fsm = &ci->otg.fsm;
 
 	intr_sts = hw_read_intr_status(ci);
 	otg_bsess_vld = hw_read_otgsc(ci, OTGSC_BSV);
 	port_conn = hw_read(ci, OP_PORTSC, PORTSC_CCS);
 
-	switch (ci->fsm.otg->state) {
+	switch (ci->otg.state) {
 	case OTG_STATE_A_WAIT_BCON:
 		if (port_conn) {
 			fsm->b_conn = 1;
@@ -737,7 +737,7 @@ irqreturn_t ci_otg_fsm_irq(struct ci_hdrc *ci)
 {
 	irqreturn_t retval =  IRQ_NONE;
 	u32 otgsc, otg_int_src = 0;
-	struct otg_fsm *fsm = &ci->fsm;
+	struct otg_fsm *fsm = &ci->otg.fsm;
 
 	otgsc = hw_read_otgsc(ci, ~0);
 	otg_int_src = otgsc & OTGSC_INT_STATUS_BITS & (otgsc >> 8);
@@ -800,17 +800,16 @@ int ci_hdrc_otg_fsm_init(struct ci_hdrc *ci)
 		ci->otg.usb_phy = ci->usb_phy;
 
 	ci->otg.gadget = &ci->gadget;
-	ci->fsm.otg = &ci->otg;
-	ci->fsm.power_up = 1;
-	ci->fsm.id = hw_read_otgsc(ci, OTGSC_ID) ? 1 : 0;
-	ci->fsm.otg->state = OTG_STATE_UNDEFINED;
-	ci->fsm.ops = &ci_otg_ops;
+	ci->otg.fsm.power_up = 1;
+	ci->otg.fsm.id = hw_read_otgsc(ci, OTGSC_ID) ? 1 : 0;
+	ci->otg.state = OTG_STATE_UNDEFINED;
+	ci->otg.fsm.ops = &ci_otg_ops;
 	ci->gadget.hnp_polling_support = 1;
-	ci->fsm.host_req_flag = devm_kzalloc(ci->dev, 1, GFP_KERNEL);
-	if (!ci->fsm.host_req_flag)
+	ci->otg.fsm.host_req_flag = devm_kzalloc(ci->dev, 1, GFP_KERNEL);
+	if (!ci->otg.fsm.host_req_flag)
 		return -ENOMEM;
 
-	mutex_init(&ci->fsm.lock);
+	mutex_init(&ci->otg.fsm.lock);
 
 	retval = ci_otg_init_timers(ci);
 	if (retval) {
@@ -830,10 +829,10 @@ int ci_hdrc_otg_fsm_init(struct ci_hdrc *ci)
 	/* Enable A vbus valid irq */
 	hw_write_otgsc(ci, OTGSC_AVVIE, OTGSC_AVVIE);
 
-	if (ci->fsm.id) {
-		ci->fsm.b_ssend_srp =
+	if (ci->otg.fsm.id) {
+		ci->otg.fsm.b_ssend_srp =
 			hw_read_otgsc(ci, OTGSC_BSV) ? 0 : 1;
-		ci->fsm.b_sess_vld =
+		ci->otg.fsm.b_sess_vld =
 			hw_read_otgsc(ci, OTGSC_BSV) ? 1 : 0;
 		/* Enable BSV irq */
 		hw_write_otgsc(ci, OTGSC_BSVIE, OTGSC_BSVIE);
diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c
index 065f5d9..7a6b0b5 100644
--- a/drivers/usb/chipidea/udc.c
+++ b/drivers/usb/chipidea/udc.c
@@ -20,6 +20,7 @@
 #include <linux/pm_runtime.h>
 #include <linux/usb/ch9.h>
 #include <linux/usb/gadget.h>
+#include <linux/usb/otg.h>
 #include <linux/usb/otg-fsm.h>
 #include <linux/usb/chipidea.h>
 
@@ -1739,7 +1740,7 @@ static int ci_udc_start(struct usb_gadget *gadget,
 	ci->driver = driver;
 
 	/* Start otg fsm for B-device */
-	if (ci_otg_is_fsm_mode(ci) && ci->fsm.id) {
+	if (ci_otg_is_fsm_mode(ci) && ci->otg.fsm.id) {
 		ci_hdrc_otg_fsm_start(ci);
 		return retval;
 	}
@@ -1767,15 +1768,15 @@ static void ci_udc_stop_for_otg_fsm(struct ci_hdrc *ci)
 	if (!ci_otg_is_fsm_mode(ci))
 		return;
 
-	mutex_lock(&ci->fsm.lock);
-	if (ci->fsm.otg->state == OTG_STATE_A_PERIPHERAL) {
-		ci->fsm.a_bidl_adis_tmout = 1;
+	mutex_lock(&ci->otg.fsm.lock);
+	if (ci->otg.state == OTG_STATE_A_PERIPHERAL) {
+		ci->otg.fsm.a_bidl_adis_tmout = 1;
 		ci_hdrc_otg_fsm_start(ci);
-	} else if (ci->fsm.otg->state == OTG_STATE_B_PERIPHERAL) {
-		ci->fsm.protocol = PROTO_UNDEF;
-		ci->fsm.otg->state = OTG_STATE_UNDEFINED;
+	} else if (ci->otg.state == OTG_STATE_B_PERIPHERAL) {
+		ci->otg.fsm.protocol = PROTO_UNDEF;
+		ci->otg.state = OTG_STATE_UNDEFINED;
 	}
-	mutex_unlock(&ci->fsm.lock);
+	mutex_unlock(&ci->otg.fsm.lock);
 }
 
 /**
diff --git a/drivers/usb/common/usb-otg-fsm.c b/drivers/usb/common/usb-otg-fsm.c
index 015cf41..4bfc6a5 100644
--- a/drivers/usb/common/usb-otg-fsm.c
+++ b/drivers/usb/common/usb-otg-fsm.c
@@ -40,6 +40,7 @@
 /* Change USB protocol when there is a protocol change */
 static int otg_set_protocol(struct otg_fsm *fsm, int protocol)
 {
+	struct usb_otg *otg = container_of(fsm, struct usb_otg, fsm);
 	int ret = 0;
 
 	if (fsm->protocol != protocol) {
@@ -47,17 +48,17 @@ static int otg_set_protocol(struct otg_fsm *fsm, int protocol)
 			fsm->protocol, protocol);
 		/* stop old protocol */
 		if (fsm->protocol == PROTO_HOST)
-			ret = otg_start_host(fsm, 0);
+			ret = otg_start_host(otg, 0);
 		else if (fsm->protocol == PROTO_GADGET)
-			ret = otg_start_gadget(fsm, 0);
+			ret = otg_start_gadget(otg, 0);
 		if (ret)
 			return ret;
 
 		/* start new protocol */
 		if (protocol == PROTO_HOST)
-			ret = otg_start_host(fsm, 1);
+			ret = otg_start_host(otg, 1);
 		else if (protocol == PROTO_GADGET)
-			ret = otg_start_gadget(fsm, 1);
+			ret = otg_start_gadget(otg, 1);
 		if (ret)
 			return ret;
 
@@ -71,9 +72,11 @@ static int otg_set_protocol(struct otg_fsm *fsm, int protocol)
 /* Called when leaving a state.  Do state clean up jobs here */
 static void otg_leave_state(struct otg_fsm *fsm, enum usb_otg_state old_state)
 {
+	struct usb_otg *otg = container_of(fsm, struct usb_otg, fsm);
+
 	switch (old_state) {
 	case OTG_STATE_B_IDLE:
-		otg_del_timer(fsm, B_SE0_SRP);
+		otg_del_timer(otg, B_SE0_SRP);
 		fsm->b_se0_srp = 0;
 		fsm->adp_sns = 0;
 		fsm->adp_prb = 0;
@@ -83,11 +86,11 @@ static void otg_leave_state(struct otg_fsm *fsm, enum usb_otg_state old_state)
 		fsm->b_srp_done = 0;
 		break;
 	case OTG_STATE_B_PERIPHERAL:
-		if (fsm->otg->gadget)
-			fsm->otg->gadget->host_request_flag = 0;
+		if (otg->gadget)
+			otg->gadget->host_request_flag = 0;
 		break;
 	case OTG_STATE_B_WAIT_ACON:
-		otg_del_timer(fsm, B_ASE0_BRST);
+		otg_del_timer(otg, B_ASE0_BRST);
 		fsm->b_ase0_brst_tmout = 0;
 		break;
 	case OTG_STATE_B_HOST:
@@ -96,31 +99,31 @@ static void otg_leave_state(struct otg_fsm *fsm, enum usb_otg_state old_state)
 		fsm->adp_prb = 0;
 		break;
 	case OTG_STATE_A_WAIT_VRISE:
-		otg_del_timer(fsm, A_WAIT_VRISE);
+		otg_del_timer(otg, A_WAIT_VRISE);
 		fsm->a_wait_vrise_tmout = 0;
 		break;
 	case OTG_STATE_A_WAIT_BCON:
-		otg_del_timer(fsm, A_WAIT_BCON);
+		otg_del_timer(otg, A_WAIT_BCON);
 		fsm->a_wait_bcon_tmout = 0;
 		break;
 	case OTG_STATE_A_HOST:
-		otg_del_timer(fsm, A_WAIT_ENUM);
+		otg_del_timer(otg, A_WAIT_ENUM);
 		break;
 	case OTG_STATE_A_SUSPEND:
-		otg_del_timer(fsm, A_AIDL_BDIS);
+		otg_del_timer(otg, A_AIDL_BDIS);
 		fsm->a_aidl_bdis_tmout = 0;
 		fsm->a_suspend_req_inf = 0;
 		break;
 	case OTG_STATE_A_PERIPHERAL:
-		otg_del_timer(fsm, A_BIDL_ADIS);
+		otg_del_timer(otg, A_BIDL_ADIS);
 		fsm->a_bidl_adis_tmout = 0;
-		if (fsm->otg->gadget)
-			fsm->otg->gadget->host_request_flag = 0;
+		if (otg->gadget)
+			otg->gadget->host_request_flag = 0;
 		break;
 	case OTG_STATE_A_WAIT_VFALL:
-		otg_del_timer(fsm, A_WAIT_VFALL);
+		otg_del_timer(otg, A_WAIT_VFALL);
 		fsm->a_wait_vfall_tmout = 0;
-		otg_del_timer(fsm, A_WAIT_VRISE);
+		otg_del_timer(otg, A_WAIT_VRISE);
 		break;
 	case OTG_STATE_A_VBUS_ERR:
 		break;
@@ -133,17 +136,18 @@ static void otg_hnp_polling_work(struct work_struct *work)
 {
 	struct otg_fsm *fsm = container_of(to_delayed_work(work),
 				struct otg_fsm, hnp_polling_work);
+	struct usb_otg *otg = container_of(fsm, struct usb_otg, fsm);
 	struct usb_device *udev;
-	enum usb_otg_state state = fsm->otg->state;
+	enum usb_otg_state state = otg->state;
 	u8 flag;
 	int retval;
 
 	if (state != OTG_STATE_A_HOST && state != OTG_STATE_B_HOST)
 		return;
 
-	udev = usb_hub_find_child(fsm->otg->host->root_hub, 1);
+	udev = usb_hub_find_child(otg->host->root_hub, 1);
 	if (!udev) {
-		dev_err(fsm->otg->host->controller,
+		dev_err(otg->host->controller,
 			"no usb dev connected, can't start HNP polling\n");
 		return;
 	}
@@ -178,7 +182,7 @@ static void otg_hnp_polling_work(struct work_struct *work)
 	/* Host request flag is set */
 	if (state == OTG_STATE_A_HOST) {
 		/* Set b_hnp_enable */
-		if (!fsm->otg->host->b_hnp_enable) {
+		if (!otg->host->b_hnp_enable) {
 			retval = usb_control_msg(udev,
 					usb_sndctrlpipe(udev, 0),
 					USB_REQ_SET_FEATURE, 0,
@@ -186,14 +190,14 @@ static void otg_hnp_polling_work(struct work_struct *work)
 					0, NULL, 0,
 					USB_CTRL_SET_TIMEOUT);
 			if (retval >= 0)
-				fsm->otg->host->b_hnp_enable = 1;
+				otg->host->b_hnp_enable = 1;
 		}
 		fsm->a_bus_req = 0;
 	} else if (state == OTG_STATE_B_HOST) {
 		fsm->b_bus_req = 0;
 	}
 
-	otg_statemachine(fsm);
+	otg_statemachine(otg);
 }
 
 static void otg_start_hnp_polling(struct otg_fsm *fsm)
@@ -213,133 +217,135 @@ static void otg_start_hnp_polling(struct otg_fsm *fsm)
 /* Called when entering a state */
 static int otg_set_state(struct otg_fsm *fsm, enum usb_otg_state new_state)
 {
-	if (fsm->otg->state == new_state)
+	struct usb_otg *otg = container_of(fsm, struct usb_otg, fsm);
+
+	if (otg->state == new_state)
 		return 0;
 	VDBG("Set state: %s\n", usb_otg_state_string(new_state));
-	otg_leave_state(fsm, fsm->otg->state);
+	otg_leave_state(fsm, otg->state);
 	switch (new_state) {
 	case OTG_STATE_B_IDLE:
-		otg_drv_vbus(fsm, 0);
-		otg_chrg_vbus(fsm, 0);
-		otg_loc_conn(fsm, 0);
-		otg_loc_sof(fsm, 0);
+		otg_drv_vbus(otg, 0);
+		otg_chrg_vbus(otg, 0);
+		otg_loc_conn(otg, 0);
+		otg_loc_sof(otg, 0);
 		/*
 		 * Driver is responsible for starting ADP probing
 		 * if ADP sensing times out.
 		 */
-		otg_start_adp_sns(fsm);
+		otg_start_adp_sns(otg);
 		otg_set_protocol(fsm, PROTO_UNDEF);
-		otg_add_timer(fsm, B_SE0_SRP);
+		otg_add_timer(otg, B_SE0_SRP);
 		break;
 	case OTG_STATE_B_SRP_INIT:
-		otg_start_pulse(fsm);
-		otg_loc_sof(fsm, 0);
+		otg_start_pulse(otg);
+		otg_loc_sof(otg, 0);
 		otg_set_protocol(fsm, PROTO_UNDEF);
-		otg_add_timer(fsm, B_SRP_FAIL);
+		otg_add_timer(otg, B_SRP_FAIL);
 		break;
 	case OTG_STATE_B_PERIPHERAL:
-		otg_chrg_vbus(fsm, 0);
-		otg_loc_sof(fsm, 0);
+		otg_chrg_vbus(otg, 0);
+		otg_loc_sof(otg, 0);
 		otg_set_protocol(fsm, PROTO_GADGET);
-		otg_loc_conn(fsm, 1);
+		otg_loc_conn(otg, 1);
 		break;
 	case OTG_STATE_B_WAIT_ACON:
-		otg_chrg_vbus(fsm, 0);
-		otg_loc_conn(fsm, 0);
-		otg_loc_sof(fsm, 0);
+		otg_chrg_vbus(otg, 0);
+		otg_loc_conn(otg, 0);
+		otg_loc_sof(otg, 0);
 		otg_set_protocol(fsm, PROTO_HOST);
-		otg_add_timer(fsm, B_ASE0_BRST);
+		otg_add_timer(otg, B_ASE0_BRST);
 		fsm->a_bus_suspend = 0;
 		break;
 	case OTG_STATE_B_HOST:
-		otg_chrg_vbus(fsm, 0);
-		otg_loc_conn(fsm, 0);
-		otg_loc_sof(fsm, 1);
+		otg_chrg_vbus(otg, 0);
+		otg_loc_conn(otg, 0);
+		otg_loc_sof(otg, 1);
 		otg_set_protocol(fsm, PROTO_HOST);
-		usb_bus_start_enum(fsm->otg->host,
-				fsm->otg->host->otg_port);
+		usb_bus_start_enum(otg->host, otg->host->otg_port);
 		otg_start_hnp_polling(fsm);
 		break;
 	case OTG_STATE_A_IDLE:
-		otg_drv_vbus(fsm, 0);
-		otg_chrg_vbus(fsm, 0);
-		otg_loc_conn(fsm, 0);
-		otg_loc_sof(fsm, 0);
-		otg_start_adp_prb(fsm);
+		otg_drv_vbus(otg, 0);
+		otg_chrg_vbus(otg, 0);
+		otg_loc_conn(otg, 0);
+		otg_loc_sof(otg, 0);
+		otg_start_adp_prb(otg);
 		otg_set_protocol(fsm, PROTO_HOST);
 		break;
 	case OTG_STATE_A_WAIT_VRISE:
-		otg_drv_vbus(fsm, 1);
-		otg_loc_conn(fsm, 0);
-		otg_loc_sof(fsm, 0);
+		otg_drv_vbus(otg, 1);
+		otg_loc_conn(otg, 0);
+		otg_loc_sof(otg, 0);
 		otg_set_protocol(fsm, PROTO_HOST);
-		otg_add_timer(fsm, A_WAIT_VRISE);
+		otg_add_timer(otg, A_WAIT_VRISE);
 		break;
 	case OTG_STATE_A_WAIT_BCON:
-		otg_drv_vbus(fsm, 1);
-		otg_loc_conn(fsm, 0);
-		otg_loc_sof(fsm, 0);
+		otg_drv_vbus(otg, 1);
+		otg_loc_conn(otg, 0);
+		otg_loc_sof(otg, 0);
 		otg_set_protocol(fsm, PROTO_HOST);
-		otg_add_timer(fsm, A_WAIT_BCON);
+		otg_add_timer(otg, A_WAIT_BCON);
 		break;
 	case OTG_STATE_A_HOST:
-		otg_drv_vbus(fsm, 1);
-		otg_loc_conn(fsm, 0);
-		otg_loc_sof(fsm, 1);
+		otg_drv_vbus(otg, 1);
+		otg_loc_conn(otg, 0);
+		otg_loc_sof(otg, 1);
 		otg_set_protocol(fsm, PROTO_HOST);
 		/*
 		 * When HNP is triggered while a_bus_req = 0, a_host will
 		 * suspend too fast to complete a_set_b_hnp_en
 		 */
 		if (!fsm->a_bus_req || fsm->a_suspend_req_inf)
-			otg_add_timer(fsm, A_WAIT_ENUM);
+			otg_add_timer(otg, A_WAIT_ENUM);
 		otg_start_hnp_polling(fsm);
 		break;
 	case OTG_STATE_A_SUSPEND:
-		otg_drv_vbus(fsm, 1);
-		otg_loc_conn(fsm, 0);
-		otg_loc_sof(fsm, 0);
+		otg_drv_vbus(otg, 1);
+		otg_loc_conn(otg, 0);
+		otg_loc_sof(otg, 0);
 		otg_set_protocol(fsm, PROTO_HOST);
-		otg_add_timer(fsm, A_AIDL_BDIS);
+		otg_add_timer(otg, A_AIDL_BDIS);
 
 		break;
 	case OTG_STATE_A_PERIPHERAL:
-		otg_loc_sof(fsm, 0);
+		otg_loc_sof(otg, 0);
 		otg_set_protocol(fsm, PROTO_GADGET);
-		otg_drv_vbus(fsm, 1);
-		otg_loc_conn(fsm, 1);
-		otg_add_timer(fsm, A_BIDL_ADIS);
+		otg_drv_vbus(otg, 1);
+		otg_loc_conn(otg, 1);
+		otg_add_timer(otg, A_BIDL_ADIS);
 		break;
 	case OTG_STATE_A_WAIT_VFALL:
-		otg_drv_vbus(fsm, 0);
-		otg_loc_conn(fsm, 0);
-		otg_loc_sof(fsm, 0);
+		otg_drv_vbus(otg, 0);
+		otg_loc_conn(otg, 0);
+		otg_loc_sof(otg, 0);
 		otg_set_protocol(fsm, PROTO_HOST);
-		otg_add_timer(fsm, A_WAIT_VFALL);
+		otg_add_timer(otg, A_WAIT_VFALL);
 		break;
 	case OTG_STATE_A_VBUS_ERR:
-		otg_drv_vbus(fsm, 0);
-		otg_loc_conn(fsm, 0);
-		otg_loc_sof(fsm, 0);
+		otg_drv_vbus(otg, 0);
+		otg_loc_conn(otg, 0);
+		otg_loc_sof(otg, 0);
 		otg_set_protocol(fsm, PROTO_UNDEF);
 		break;
 	default:
 		break;
 	}
 
-	fsm->otg->state = new_state;
+	otg->state = new_state;
 	fsm->state_changed = 1;
 	return 0;
 }
 
 /* State change judgement */
-int otg_statemachine(struct otg_fsm *fsm)
+int otg_statemachine(struct usb_otg *otg)
 {
 	enum usb_otg_state state;
+	struct otg_fsm *fsm = &otg->fsm;
 
 	mutex_lock(&fsm->lock);
 
-	state = fsm->otg->state;
+	state = otg->state;
 	fsm->state_changed = 0;
 	/* State machine state change judgement */
 
@@ -354,7 +360,7 @@ int otg_statemachine(struct otg_fsm *fsm)
 	case OTG_STATE_B_IDLE:
 		if (!fsm->id)
 			otg_set_state(fsm, OTG_STATE_A_IDLE);
-		else if (fsm->b_sess_vld && fsm->otg->gadget)
+		else if (fsm->b_sess_vld && otg->gadget)
 			otg_set_state(fsm, OTG_STATE_B_PERIPHERAL);
 		else if ((fsm->b_bus_req || fsm->adp_change || fsm->power_up) &&
 				fsm->b_ssend_srp && fsm->b_se0_srp)
@@ -367,8 +373,8 @@ int otg_statemachine(struct otg_fsm *fsm)
 	case OTG_STATE_B_PERIPHERAL:
 		if (!fsm->id || !fsm->b_sess_vld)
 			otg_set_state(fsm, OTG_STATE_B_IDLE);
-		else if (fsm->b_bus_req && fsm->otg->
-				gadget->b_hnp_enable && fsm->a_bus_suspend)
+		else if (fsm->b_bus_req && otg->gadget->b_hnp_enable &&
+			 fsm->a_bus_suspend)
 			otg_set_state(fsm, OTG_STATE_B_WAIT_ACON);
 		break;
 	case OTG_STATE_B_WAIT_ACON:
@@ -413,7 +419,7 @@ int otg_statemachine(struct otg_fsm *fsm)
 		if (fsm->id || fsm->a_bus_drop)
 			otg_set_state(fsm, OTG_STATE_A_WAIT_VFALL);
 		else if ((!fsm->a_bus_req || fsm->a_suspend_req_inf) &&
-				fsm->otg->host->b_hnp_enable)
+			 otg->host->b_hnp_enable)
 			otg_set_state(fsm, OTG_STATE_A_SUSPEND);
 		else if (!fsm->b_conn)
 			otg_set_state(fsm, OTG_STATE_A_WAIT_BCON);
@@ -421,9 +427,9 @@ int otg_statemachine(struct otg_fsm *fsm)
 			otg_set_state(fsm, OTG_STATE_A_VBUS_ERR);
 		break;
 	case OTG_STATE_A_SUSPEND:
-		if (!fsm->b_conn && fsm->otg->host->b_hnp_enable)
+		if (!fsm->b_conn && otg->host->b_hnp_enable)
 			otg_set_state(fsm, OTG_STATE_A_PERIPHERAL);
-		else if (!fsm->b_conn && !fsm->otg->host->b_hnp_enable)
+		else if (!fsm->b_conn && !otg->host->b_hnp_enable)
 			otg_set_state(fsm, OTG_STATE_A_WAIT_BCON);
 		else if (fsm->a_bus_req || fsm->b_bus_resume)
 			otg_set_state(fsm, OTG_STATE_A_HOST);
diff --git a/drivers/usb/phy/phy-fsl-usb.c b/drivers/usb/phy/phy-fsl-usb.c
index dd8a1ad..587a187 100644
--- a/drivers/usb/phy/phy-fsl-usb.c
+++ b/drivers/usb/phy/phy-fsl-usb.c
@@ -127,7 +127,7 @@ int write_ulpi(u8 addr, u8 data)
 /* Operations that will be called from OTG Finite State Machine */
 
 /* Charge vbus for vbus pulsing in SRP */
-void fsl_otg_chrg_vbus(struct otg_fsm *fsm, int on)
+void fsl_otg_chrg_vbus(struct usb_otg *otg, int on)
 {
 	u32 tmp;
 
@@ -163,7 +163,7 @@ void fsl_otg_dischrg_vbus(int on)
 }
 
 /* A-device driver vbus, controlled through PP bit in PORTSC */
-void fsl_otg_drv_vbus(struct otg_fsm *fsm, int on)
+void fsl_otg_drv_vbus(struct usb_otg *otg, int on)
 {
 	u32 tmp;
 
@@ -181,7 +181,7 @@ void fsl_otg_drv_vbus(struct otg_fsm *fsm, int on)
  * Pull-up D+, signalling connect by periperal. Also used in
  * data-line pulsing in SRP
  */
-void fsl_otg_loc_conn(struct otg_fsm *fsm, int on)
+void fsl_otg_loc_conn(struct usb_otg *otg, int on)
 {
 	u32 tmp;
 
@@ -200,7 +200,7 @@ void fsl_otg_loc_conn(struct otg_fsm *fsm, int on)
  * port.  In host mode, controller will automatically send SOF.
  * Suspend will block the data on the port.
  */
-void fsl_otg_loc_sof(struct otg_fsm *fsm, int on)
+void fsl_otg_loc_sof(struct usb_otg *otg, int on)
 {
 	u32 tmp;
 
@@ -215,7 +215,7 @@ void fsl_otg_loc_sof(struct otg_fsm *fsm, int on)
 }
 
 /* Start SRP pulsing by data-line pulsing, followed with v-bus pulsing. */
-void fsl_otg_start_pulse(struct otg_fsm *fsm)
+void fsl_otg_start_pulse(struct usb_otg *otg)
 {
 	u32 tmp;
 
@@ -228,7 +228,7 @@ void fsl_otg_start_pulse(struct otg_fsm *fsm)
 	fsl_otg_loc_conn(1);
 #endif
 
-	fsl_otg_add_timer(fsm, b_data_pulse_tmr);
+	fsl_otg_add_timer(&otg->fsm, b_data_pulse_tmr);
 }
 
 void b_data_pulse_end(unsigned long foo)
@@ -245,14 +245,14 @@ void b_data_pulse_end(unsigned long foo)
 void fsl_otg_pulse_vbus(void)
 {
 	srp_wait_done = 0;
-	fsl_otg_chrg_vbus(&fsl_otg_dev->fsm, 1);
+	fsl_otg_chrg_vbus(&fsl_otg_dev->otg, 1);
 	/* start the timer to end vbus charge */
-	fsl_otg_add_timer(&fsl_otg_dev->fsm, b_vbus_pulse_tmr);
+	fsl_otg_add_timer(&fsl_otg_dev->otg.fsm, b_vbus_pulse_tmr);
 }
 
 void b_vbus_pulse_end(unsigned long foo)
 {
-	fsl_otg_chrg_vbus(&fsl_otg_dev->fsm, 0);
+	fsl_otg_chrg_vbus(&fsl_otg_dev->otg, 0);
 
 	/*
 	 * As USB3300 using the same a_sess_vld and b_sess_vld voltage
@@ -260,7 +260,7 @@ void b_vbus_pulse_end(unsigned long foo)
 	 * residual voltage of vbus pulsing and A device pull up
 	 */
 	fsl_otg_dischrg_vbus(1);
-	fsl_otg_add_timer(&fsl_otg_dev->fsm, b_srp_wait_tmr);
+	fsl_otg_add_timer(&fsl_otg_dev->otg.fsm, b_srp_wait_tmr);
 }
 
 void b_srp_end(unsigned long foo)
@@ -269,8 +269,8 @@ void b_srp_end(unsigned long foo)
 	srp_wait_done = 1;
 
 	if ((fsl_otg_dev->phy.otg->state == OTG_STATE_B_SRP_INIT) &&
-	    fsl_otg_dev->fsm.b_sess_vld)
-		fsl_otg_dev->fsm.b_srp_done = 1;
+	    fsl_otg_dev->otg.fsm.b_sess_vld)
+		fsl_otg_dev->otg.fsm.b_srp_done = 1;
 }
 
 /*
@@ -282,9 +282,9 @@ void a_wait_enum(unsigned long foo)
 {
 	VDBG("a_wait_enum timeout\n");
 	if (!fsl_otg_dev->phy.otg->host->b_hnp_enable)
-		fsl_otg_add_timer(&fsl_otg_dev->fsm, a_wait_enum_tmr);
+		fsl_otg_add_timer(&fsl_otg_dev->otg.fsm, a_wait_enum_tmr);
 	else
-		otg_statemachine(&fsl_otg_dev->fsm);
+		otg_statemachine(&fsl_otg_dev->otg);
 }
 
 /* The timeout callback function to set time out bit */
@@ -421,7 +421,7 @@ void fsl_otg_add_timer(struct otg_fsm *fsm, void *gtimer)
 	list_add_tail(&timer->list, &active_timers);
 }
 
-static void fsl_otg_fsm_add_timer(struct otg_fsm *fsm, enum otg_fsm_timer t)
+static void fsl_otg_fsm_add_timer(struct usb_otg *otg, enum otg_fsm_timer t)
 {
 	struct fsl_otg_timer *timer;
 
@@ -429,7 +429,7 @@ static void fsl_otg_fsm_add_timer(struct otg_fsm *fsm, enum otg_fsm_timer t)
 	if (!timer)
 		return;
 
-	fsl_otg_add_timer(fsm, timer);
+	fsl_otg_add_timer(&otg->fsm, timer);
 }
 
 /* Remove timer from the timer list; clear timeout status */
@@ -443,7 +443,7 @@ void fsl_otg_del_timer(struct otg_fsm *fsm, void *gtimer)
 			list_del(&timer->list);
 }
 
-static void fsl_otg_fsm_del_timer(struct otg_fsm *fsm, enum otg_fsm_timer t)
+static void fsl_otg_fsm_del_timer(struct usb_otg *otg, enum otg_fsm_timer t)
 {
 	struct fsl_otg_timer *timer;
 
@@ -451,7 +451,7 @@ static void fsl_otg_fsm_del_timer(struct otg_fsm *fsm, enum otg_fsm_timer t)
 	if (!timer)
 		return;
 
-	fsl_otg_del_timer(fsm, timer);
+	fsl_otg_del_timer(&otg->fsm, timer);
 }
 
 /* Reset controller, not reset the bus */
@@ -467,9 +467,9 @@ void otg_reset_controller(void)
 }
 
 /* Call suspend/resume routines in host driver */
-int fsl_otg_start_host(struct otg_fsm *fsm, int on)
+int fsl_otg_start_host(struct usb_otg *otg, int on)
 {
-	struct usb_otg *otg = fsm->otg;
+	struct otg_fsm *fsm = &otg->fsm;
 	struct device *dev;
 	struct fsl_otg *otg_dev =
 		container_of(otg->usb_phy, struct fsl_otg, phy);
@@ -496,7 +496,7 @@ int fsl_otg_start_host(struct otg_fsm *fsm, int on)
 				retval = dev->driver->pm->resume(dev);
 				if (fsm->id) {
 					/* default-b */
-					fsl_otg_drv_vbus(fsm, 1);
+					fsl_otg_drv_vbus(otg, 1);
 					/*
 					 * Workaround: b_host can't driver
 					 * vbus, but PP in PORTSC needs to
@@ -521,7 +521,7 @@ int fsl_otg_start_host(struct otg_fsm *fsm, int on)
 					retval = dev->driver->pm->suspend(dev);
 				if (fsm->id)
 					/* default-b */
-					fsl_otg_drv_vbus(fsm, 0);
+					fsl_otg_drv_vbus(otg, 0);
 			}
 			otg_dev->host_working = 0;
 		}
@@ -534,9 +534,8 @@ end:
  * Call suspend and resume function in udc driver
  * to stop and start udc driver.
  */
-int fsl_otg_start_gadget(struct otg_fsm *fsm, int on)
+int fsl_otg_start_gadget(struct usb_otg *otg, int on)
 {
-	struct usb_otg *otg = fsm->otg;
 	struct device *dev;
 
 	if (!otg->gadget || !otg->gadget->dev.parent)
@@ -573,14 +572,14 @@ static int fsl_otg_set_host(struct usb_otg *otg, struct usb_bus *host)
 
 	otg->host = host;
 
-	otg_dev->fsm.a_bus_drop = 0;
-	otg_dev->fsm.a_bus_req = 1;
+	otg->fsm.a_bus_drop = 0;
+	otg->fsm.a_bus_req = 1;
 
 	if (host) {
 		VDBG("host off......\n");
 
 		otg->host->otg_port = fsl_otg_initdata.otg_port;
-		otg->host->is_b_host = otg_dev->fsm.id;
+		otg->host->is_b_host = otg->fsm.id;
 		/*
 		 * must leave time for hub_wq to finish its thing
 		 * before yanking the host driver out from under it,
@@ -594,7 +593,7 @@ static int fsl_otg_set_host(struct usb_otg *otg, struct usb_bus *host)
 		if (!(fsl_readl(&otg_dev->dr_mem_map->otgsc) &
 		      OTGSC_STS_USB_ID)) {
 			/* Mini-A cable connected */
-			struct otg_fsm *fsm = &otg_dev->fsm;
+			struct otg_fsm *fsm = &otg->fsm;
 
 			otg->state = OTG_STATE_UNDEFINED;
 			fsm->protocol = PROTO_UNDEF;
@@ -603,7 +602,7 @@ static int fsl_otg_set_host(struct usb_otg *otg, struct usb_bus *host)
 
 	otg_dev->host_working = 0;
 
-	otg_statemachine(&otg_dev->fsm);
+	otg_statemachine(otg);
 
 	return 0;
 }
@@ -628,22 +627,22 @@ static int fsl_otg_set_peripheral(struct usb_otg *otg,
 			otg->gadget->ops->vbus_draw(otg->gadget, 0);
 		usb_gadget_vbus_disconnect(otg->gadget);
 		otg->gadget = 0;
-		otg_dev->fsm.b_bus_req = 0;
-		otg_statemachine(&otg_dev->fsm);
+		otg->fsm.b_bus_req = 0;
+		otg_statemachine(otg);
 		return 0;
 	}
 
 	otg->gadget = gadget;
-	otg->gadget->is_a_peripheral = !otg_dev->fsm.id;
+	otg->gadget->is_a_peripheral = !otg->fsm.id;
 
-	otg_dev->fsm.b_bus_req = 1;
+	otg->fsm.b_bus_req = 1;
 
 	/* start the gadget right away if the ID pin says Mini-B */
-	pr_debug("ID pin=%d\n", otg_dev->fsm.id);
-	if (otg_dev->fsm.id == 1) {
-		fsl_otg_start_host(&otg_dev->fsm, 0);
-		otg_drv_vbus(&otg_dev->fsm, 0);
-		fsl_otg_start_gadget(&otg_dev->fsm, 1);
+	pr_debug("ID pin=%d\n", otg->fsm.id);
+	if (otg->fsm.id == 1) {
+		fsl_otg_start_host(otg, 0);
+		otg_drv_vbus(otg, 0);
+		fsl_otg_start_gadget(otg, 1);
 	}
 
 	return 0;
@@ -672,13 +671,14 @@ static int fsl_otg_set_power(struct usb_phy *phy, unsigned mA)
  */
 static void fsl_otg_event(struct work_struct *work)
 {
-	struct fsl_otg *og = container_of(work, struct fsl_otg, otg_event.work);
-	struct otg_fsm *fsm = &og->fsm;
-
-	if (fsm->id) {		/* switch to gadget */
-		fsl_otg_start_host(fsm, 0);
-		otg_drv_vbus(fsm, 0);
-		fsl_otg_start_gadget(fsm, 1);
+	struct fsl_otg *fotg = container_of(work, struct fsl_otg,
+					    otg_event.work);
+	struct usb_otg *otg = &fotg->otg;
+
+	if (otg->fsm.id) {		/* switch to gadget */
+		fsl_otg_start_host(otg, 0);
+		otg_drv_vbus(otg, 0);
+		fsl_otg_start_gadget(otg, 1);
 	}
 }
 
@@ -694,8 +694,8 @@ static int fsl_otg_start_srp(struct usb_otg *otg)
 	if (otg_dev != fsl_otg_dev)
 		return -ENODEV;
 
-	otg_dev->fsm.b_bus_req = 1;
-	otg_statemachine(&otg_dev->fsm);
+	otg->fsm.b_bus_req = 1;
+	otg_statemachine(otg);
 
 	return 0;
 }
@@ -715,8 +715,8 @@ static int fsl_otg_start_hnp(struct usb_otg *otg)
 	pr_debug("start_hnp...\n");
 
 	/* clear a_bus_req to enter a_suspend state */
-	otg_dev->fsm.a_bus_req = 0;
-	otg_statemachine(&otg_dev->fsm);
+	otg->fsm.a_bus_req = 0;
+	otg_statemachine(otg);
 
 	return 0;
 }
@@ -729,8 +729,8 @@ static int fsl_otg_start_hnp(struct usb_otg *otg)
  */
 irqreturn_t fsl_otg_isr(int irq, void *dev_id)
 {
-	struct otg_fsm *fsm = &((struct fsl_otg *)dev_id)->fsm;
-	struct usb_otg *otg = ((struct fsl_otg *)dev_id)->phy.otg;
+	struct usb_otg *otg = &((struct fsl_otg *)dev_id)->otg;
+	struct otg_fsm *fsm = &otg->fsm;
 	u32 otg_int_src, otg_sc;
 
 	otg_sc = fsl_readl(&usb_dr_regs->otgsc);
@@ -768,9 +768,9 @@ irqreturn_t fsl_otg_isr(int irq, void *dev_id)
 				cancel_delayed_work(&
 						    ((struct fsl_otg *)dev_id)->
 						    otg_event);
-				fsl_otg_start_gadget(fsm, 0);
-				otg_drv_vbus(fsm, 1);
-				fsl_otg_start_host(fsm, 1);
+				fsl_otg_start_gadget(otg, 0);
+				otg_drv_vbus(otg, 1);
+				fsl_otg_start_host(otg, 1);
 			}
 			return IRQ_HANDLED;
 		}
@@ -806,24 +806,20 @@ static int fsl_otg_conf(struct platform_device *pdev)
 	if (!fsl_otg_tc)
 		return -ENOMEM;
 
-	fsl_otg_tc->phy.otg = kzalloc(sizeof(struct usb_otg), GFP_KERNEL);
-	if (!fsl_otg_tc->phy.otg) {
-		kfree(fsl_otg_tc);
-		return -ENOMEM;
-	}
+	fsl_otg_tc->phy.otg = &fsl_otg_tc->otg;
 
 	INIT_DELAYED_WORK(&fsl_otg_tc->otg_event, fsl_otg_event);
 
 	INIT_LIST_HEAD(&active_timers);
-	status = fsl_otg_init_timers(&fsl_otg_tc->fsm);
+	status = fsl_otg_init_timers(&fsl_otg_tc->otg.fsm);
 	if (status) {
 		pr_info("Couldn't init OTG timers\n");
 		goto err;
 	}
-	mutex_init(&fsl_otg_tc->fsm.lock);
+	mutex_init(&fsl_otg_tc->otg.fsm.lock);
 
 	/* Set OTG state machine operations */
-	fsl_otg_tc->fsm.ops = &fsl_otg_ops;
+	fsl_otg_tc->otg.fsm.ops = &fsl_otg_ops;
 
 	/* initialize the otg structure */
 	fsl_otg_tc->phy.label = DRIVER_DESC;
@@ -858,18 +854,15 @@ int usb_otg_start(struct platform_device *pdev)
 {
 	struct fsl_otg *p_otg;
 	struct usb_phy *otg_trans = usb_get_phy(USB_PHY_TYPE_USB2);
-	struct otg_fsm *fsm;
 	int status;
 	struct resource *res;
 	u32 temp;
 	struct fsl_usb2_platform_data *pdata = dev_get_platdata(&pdev->dev);
 
 	p_otg = container_of(otg_trans, struct fsl_otg, phy);
-	fsm = &p_otg->fsm;
 
 	/* Initialize the state machine structure with default values */
 	SET_OTG_STATE(otg_trans, OTG_STATE_UNDEFINED);
-	fsm->otg = p_otg->phy.otg;
 
 	/* We don't require predefined MEM/IRQ resource index */
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -963,13 +956,13 @@ int usb_otg_start(struct platform_device *pdev)
 	 */
 	if (fsl_readl(&p_otg->dr_mem_map->otgsc) & OTGSC_STS_USB_ID) {
 		p_otg->phy.otg->state = OTG_STATE_UNDEFINED;
-		p_otg->fsm.id = 1;
+		p_otg->otg.fsm.id = 1;
 	} else {
 		p_otg->phy.otg->state = OTG_STATE_A_IDLE;
-		p_otg->fsm.id = 0;
+		p_otg->otg.fsm.id = 0;
 	}
 
-	pr_debug("initial ID pin=%d\n", p_otg->fsm.id);
+	pr_debug("initial ID pin=%d\n", p_otg->otg.fsm.id);
 
 	/* enable OTG ID pin interrupt */
 	temp = fsl_readl(&p_otg->dr_mem_map->otgsc);
@@ -986,7 +979,7 @@ int usb_otg_start(struct platform_device *pdev)
 static int show_fsl_usb2_otg_state(struct device *dev,
 				   struct device_attribute *attr, char *buf)
 {
-	struct otg_fsm *fsm = &fsl_otg_dev->fsm;
+	struct otg_fsm *fsm = &fsl_otg_dev->otg.fsm;
 	char *next = buf;
 	unsigned size = PAGE_SIZE;
 	int t;
@@ -1084,26 +1077,26 @@ static long fsl_otg_ioctl(struct file *file, unsigned int cmd,
 		break;
 
 	case SET_A_SUSPEND_REQ:
-		fsl_otg_dev->fsm.a_suspend_req_inf = arg;
+		fsl_otg_dev->otg.fsm.a_suspend_req_inf = arg;
 		break;
 
 	case SET_A_BUS_DROP:
-		fsl_otg_dev->fsm.a_bus_drop = arg;
+		fsl_otg_dev->otg.fsm.a_bus_drop = arg;
 		break;
 
 	case SET_A_BUS_REQ:
-		fsl_otg_dev->fsm.a_bus_req = arg;
+		fsl_otg_dev->otg.fsm.a_bus_req = arg;
 		break;
 
 	case SET_B_BUS_REQ:
-		fsl_otg_dev->fsm.b_bus_req = arg;
+		fsl_otg_dev->otg.fsm.b_bus_req = arg;
 		break;
 
 	default:
 		break;
 	}
 
-	otg_statemachine(&fsl_otg_dev->fsm);
+	otg_statemachine(&fsl_otg_dev->otg);
 
 	return retval;
 }
diff --git a/drivers/usb/phy/phy-fsl-usb.h b/drivers/usb/phy/phy-fsl-usb.h
index 2314995..e207cfb 100644
--- a/drivers/usb/phy/phy-fsl-usb.h
+++ b/drivers/usb/phy/phy-fsl-usb.h
@@ -15,7 +15,6 @@
  * 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#include <linux/usb/otg-fsm.h>
 #include <linux/usb/otg.h>
 #include <linux/ioctl.h>
 
@@ -370,7 +369,7 @@ inline struct fsl_otg_timer *otg_timer_initializer
 
 struct fsl_otg {
 	struct usb_phy phy;
-	struct otg_fsm fsm;
+	struct usb_otg otg;
 	struct usb_dr_mmap *dr_mem_map;
 	struct delayed_work otg_event;
 
diff --git a/include/linux/usb/otg-fsm.h b/include/linux/usb/otg-fsm.h
index a0a8f87..26e6531 100644
--- a/include/linux/usb/otg-fsm.h
+++ b/include/linux/usb/otg-fsm.h
@@ -188,7 +188,6 @@ struct otg_fsm {
 	int a_bidl_adis_tmout;
 
 	struct otg_fsm_ops *ops;
-	struct usb_otg *otg;
 
 	/* Current usb protocol used: 0:undefine; 1:host; 2:client */
 	int protocol;
@@ -198,126 +197,23 @@ struct otg_fsm {
 	bool state_changed;
 };
 
+struct usb_otg;
+
 struct otg_fsm_ops {
-	void	(*chrg_vbus)(struct otg_fsm *fsm, int on);
-	void	(*drv_vbus)(struct otg_fsm *fsm, int on);
-	void	(*loc_conn)(struct otg_fsm *fsm, int on);
-	void	(*loc_sof)(struct otg_fsm *fsm, int on);
-	void	(*start_pulse)(struct otg_fsm *fsm);
-	void	(*start_adp_prb)(struct otg_fsm *fsm);
-	void	(*start_adp_sns)(struct otg_fsm *fsm);
-	void	(*add_timer)(struct otg_fsm *fsm, enum otg_fsm_timer timer);
-	void	(*del_timer)(struct otg_fsm *fsm, enum otg_fsm_timer timer);
-	int	(*start_host)(struct otg_fsm *fsm, int on);
-	int	(*start_gadget)(struct otg_fsm *fsm, int on);
+	void	(*chrg_vbus)(struct usb_otg *otg, int on);
+	void	(*drv_vbus)(struct usb_otg *otg, int on);
+	void	(*loc_conn)(struct usb_otg *otg, int on);
+	void	(*loc_sof)(struct usb_otg *otg, int on);
+	void	(*start_pulse)(struct usb_otg *otg);
+	void	(*start_adp_prb)(struct usb_otg *otg);
+	void	(*start_adp_sns)(struct usb_otg *otg);
+	void	(*add_timer)(struct usb_otg *otg, enum otg_fsm_timer timer);
+	void	(*del_timer)(struct usb_otg *otg, enum otg_fsm_timer timer);
+	int	(*start_host)(struct usb_otg *otg, int on);
+	int	(*start_gadget)(struct usb_otg *otg, int on);
 };
 
 
-static inline int otg_chrg_vbus(struct otg_fsm *fsm, int on)
-{
-	if (!fsm->ops->chrg_vbus)
-		return -EOPNOTSUPP;
-	fsm->ops->chrg_vbus(fsm, on);
-	return 0;
-}
-
-static inline int otg_drv_vbus(struct otg_fsm *fsm, int on)
-{
-	if (!fsm->ops->drv_vbus)
-		return -EOPNOTSUPP;
-	if (fsm->drv_vbus != on) {
-		fsm->drv_vbus = on;
-		fsm->ops->drv_vbus(fsm, on);
-	}
-	return 0;
-}
-
-static inline int otg_loc_conn(struct otg_fsm *fsm, int on)
-{
-	if (!fsm->ops->loc_conn)
-		return -EOPNOTSUPP;
-	if (fsm->loc_conn != on) {
-		fsm->loc_conn = on;
-		fsm->ops->loc_conn(fsm, on);
-	}
-	return 0;
-}
-
-static inline int otg_loc_sof(struct otg_fsm *fsm, int on)
-{
-	if (!fsm->ops->loc_sof)
-		return -EOPNOTSUPP;
-	if (fsm->loc_sof != on) {
-		fsm->loc_sof = on;
-		fsm->ops->loc_sof(fsm, on);
-	}
-	return 0;
-}
-
-static inline int otg_start_pulse(struct otg_fsm *fsm)
-{
-	if (!fsm->ops->start_pulse)
-		return -EOPNOTSUPP;
-	if (!fsm->data_pulse) {
-		fsm->data_pulse = 1;
-		fsm->ops->start_pulse(fsm);
-	}
-	return 0;
-}
-
-static inline int otg_start_adp_prb(struct otg_fsm *fsm)
-{
-	if (!fsm->ops->start_adp_prb)
-		return -EOPNOTSUPP;
-	if (!fsm->adp_prb) {
-		fsm->adp_sns = 0;
-		fsm->adp_prb = 1;
-		fsm->ops->start_adp_prb(fsm);
-	}
-	return 0;
-}
-
-static inline int otg_start_adp_sns(struct otg_fsm *fsm)
-{
-	if (!fsm->ops->start_adp_sns)
-		return -EOPNOTSUPP;
-	if (!fsm->adp_sns) {
-		fsm->adp_sns = 1;
-		fsm->ops->start_adp_sns(fsm);
-	}
-	return 0;
-}
-
-static inline int otg_add_timer(struct otg_fsm *fsm, enum otg_fsm_timer timer)
-{
-	if (!fsm->ops->add_timer)
-		return -EOPNOTSUPP;
-	fsm->ops->add_timer(fsm, timer);
-	return 0;
-}
-
-static inline int otg_del_timer(struct otg_fsm *fsm, enum otg_fsm_timer timer)
-{
-	if (!fsm->ops->del_timer)
-		return -EOPNOTSUPP;
-	fsm->ops->del_timer(fsm, timer);
-	return 0;
-}
-
-static inline int otg_start_host(struct otg_fsm *fsm, int on)
-{
-	if (!fsm->ops->start_host)
-		return -EOPNOTSUPP;
-	return fsm->ops->start_host(fsm, on);
-}
-
-static inline int otg_start_gadget(struct otg_fsm *fsm, int on)
-{
-	if (!fsm->ops->start_gadget)
-		return -EOPNOTSUPP;
-	return fsm->ops->start_gadget(fsm, on);
-}
-
-int otg_statemachine(struct otg_fsm *fsm);
+int otg_statemachine(struct usb_otg *otg);
 
 #endif /* __LINUX_USB_OTG_FSM_H */
diff --git a/include/linux/usb/otg.h b/include/linux/usb/otg.h
index 67929df..e8a14dc 100644
--- a/include/linux/usb/otg.h
+++ b/include/linux/usb/otg.h
@@ -11,6 +11,7 @@
 
 #include <linux/phy/phy.h>
 #include <linux/usb/phy.h>
+#include <linux/usb/otg-fsm.h>
 
 struct usb_otg {
 	u8			default_a;
@@ -22,6 +23,7 @@ struct usb_otg {
 	struct usb_gadget	*gadget;
 
 	enum usb_otg_state	state;
+	struct otg_fsm fsm;
 
 	/* bind/unbind the host controller */
 	int	(*set_host)(struct usb_otg *otg, struct usb_bus *host);
@@ -128,4 +130,109 @@ enum usb_dr_mode {
  */
 extern enum usb_dr_mode usb_get_dr_mode(struct device *dev);
 
+static inline int otg_chrg_vbus(struct usb_otg *otg, int on)
+{
+	if (!otg->fsm.ops->chrg_vbus)
+		return -EOPNOTSUPP;
+	otg->fsm.ops->chrg_vbus(otg, on);
+	return 0;
+}
+
+static inline int otg_drv_vbus(struct usb_otg *otg, int on)
+{
+	if (!otg->fsm.ops->drv_vbus)
+		return -EOPNOTSUPP;
+	if (otg->fsm.drv_vbus != on) {
+		otg->fsm.drv_vbus = on;
+		otg->fsm.ops->drv_vbus(otg, on);
+	}
+	return 0;
+}
+
+static inline int otg_loc_conn(struct usb_otg *otg, int on)
+{
+	if (!otg->fsm.ops->loc_conn)
+		return -EOPNOTSUPP;
+	if (otg->fsm.loc_conn != on) {
+		otg->fsm.loc_conn = on;
+		otg->fsm.ops->loc_conn(otg, on);
+	}
+	return 0;
+}
+
+static inline int otg_loc_sof(struct usb_otg *otg, int on)
+{
+	if (!otg->fsm.ops->loc_sof)
+		return -EOPNOTSUPP;
+	if (otg->fsm.loc_sof != on) {
+		otg->fsm.loc_sof = on;
+		otg->fsm.ops->loc_sof(otg, on);
+	}
+	return 0;
+}
+
+static inline int otg_start_pulse(struct usb_otg *otg)
+{
+	if (!otg->fsm.ops->start_pulse)
+		return -EOPNOTSUPP;
+	if (!otg->fsm.data_pulse) {
+		otg->fsm.data_pulse = 1;
+		otg->fsm.ops->start_pulse(otg);
+	}
+	return 0;
+}
+
+static inline int otg_start_adp_prb(struct usb_otg *otg)
+{
+	if (!otg->fsm.ops->start_adp_prb)
+		return -EOPNOTSUPP;
+	if (!otg->fsm.adp_prb) {
+		otg->fsm.adp_sns = 0;
+		otg->fsm.adp_prb = 1;
+		otg->fsm.ops->start_adp_prb(otg);
+	}
+	return 0;
+}
+
+static inline int otg_start_adp_sns(struct usb_otg *otg)
+{
+	if (!otg->fsm.ops->start_adp_sns)
+		return -EOPNOTSUPP;
+	if (!otg->fsm.adp_sns) {
+		otg->fsm.adp_sns = 1;
+		otg->fsm.ops->start_adp_sns(otg);
+	}
+	return 0;
+}
+
+static inline int otg_add_timer(struct usb_otg *otg, enum otg_fsm_timer timer)
+{
+	if (!otg->fsm.ops->add_timer)
+		return -EOPNOTSUPP;
+	otg->fsm.ops->add_timer(otg, timer);
+	return 0;
+}
+
+static inline int otg_del_timer(struct usb_otg *otg, enum otg_fsm_timer timer)
+{
+	if (!otg->fsm.ops->del_timer)
+		return -EOPNOTSUPP;
+	otg->fsm.ops->del_timer(otg, timer);
+	return 0;
+}
+
+static inline int otg_start_host(struct usb_otg *otg, int on)
+{
+	if (!otg->fsm.ops->start_host)
+		return -EOPNOTSUPP;
+	return otg->fsm.ops->start_host(otg, on);
+}
+
+static inline int otg_start_gadget(struct usb_otg *otg, int on)
+{
+	if (!otg->fsm.ops->start_gadget)
+		return -EOPNOTSUPP;
+	return otg->fsm.ops->start_gadget(otg, on);
+}
+
 #endif /* __LINUX_USB_OTG_H */
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH v8 05/14] usb: otg-fsm: move host controller operations into usb_otg->hcd_ops
  2016-05-13 10:03 [PATCH v8 00/14] USB OTG/dual-role framework Roger Quadros
                   ` (3 preceding siblings ...)
  2016-05-13 10:03 ` [PATCH v8 04/14] usb: otg-fsm: use usb_otg wherever possible Roger Quadros
@ 2016-05-13 10:03 ` Roger Quadros
  2016-05-13 10:03 ` [PATCH v8 06/14] usb: gadget.h: Add OTG to gadget interface Roger Quadros
                   ` (9 subsequent siblings)
  14 siblings, 0 replies; 62+ messages in thread
From: Roger Quadros @ 2016-05-13 10:03 UTC (permalink / raw)
  To: peter.chen
  Cc: balbi, tony, gregkh, dan.j.williams, mathias.nyman, Joao.Pinto,
	sergei.shtylyov, jun.li, grygorii.strashko, yoshihiro.shimoda.uh,
	robh, nsekhar, b-liu, linux-usb, linux-omap, linux-kernel,
	devicetree, Roger Quadros

This is to prevent missing symbol build error if OTG is
enabled (built-in) and HCD core (CONFIG_USB) is module.

Signed-off-by: Roger Quadros <rogerq@ti.com>
Acked-by: Peter Chen <peter.chen@nxp.com>
---
 drivers/usb/chipidea/otg_fsm.c   |  7 +++++++
 drivers/usb/common/usb-otg-fsm.c | 15 +++++++++++----
 drivers/usb/phy/phy-fsl-usb.c    |  7 +++++++
 include/linux/usb/otg.h          |  2 ++
 4 files changed, 27 insertions(+), 4 deletions(-)

diff --git a/drivers/usb/chipidea/otg_fsm.c b/drivers/usb/chipidea/otg_fsm.c
index 1c0c750..2d8d659 100644
--- a/drivers/usb/chipidea/otg_fsm.c
+++ b/drivers/usb/chipidea/otg_fsm.c
@@ -582,6 +582,12 @@ static struct otg_fsm_ops ci_otg_ops = {
 	.start_gadget = ci_otg_start_gadget,
 };
 
+static struct otg_hcd_ops ci_hcd_ops = {
+	.usb_bus_start_enum = usb_bus_start_enum,
+	.usb_control_msg = usb_control_msg,
+	.usb_hub_find_child = usb_hub_find_child,
+};
+
 int ci_otg_fsm_work(struct ci_hdrc *ci)
 {
 	/*
@@ -804,6 +810,7 @@ int ci_hdrc_otg_fsm_init(struct ci_hdrc *ci)
 	ci->otg.fsm.id = hw_read_otgsc(ci, OTGSC_ID) ? 1 : 0;
 	ci->otg.state = OTG_STATE_UNDEFINED;
 	ci->otg.fsm.ops = &ci_otg_ops;
+	ci->otg.hcd_ops = &ci_hcd_ops;
 	ci->gadget.hnp_polling_support = 1;
 	ci->otg.fsm.host_req_flag = devm_kzalloc(ci->dev, 1, GFP_KERNEL);
 	if (!ci->otg.fsm.host_req_flag)
diff --git a/drivers/usb/common/usb-otg-fsm.c b/drivers/usb/common/usb-otg-fsm.c
index 4bfc6a5..2986b66 100644
--- a/drivers/usb/common/usb-otg-fsm.c
+++ b/drivers/usb/common/usb-otg-fsm.c
@@ -141,11 +141,16 @@ static void otg_hnp_polling_work(struct work_struct *work)
 	enum usb_otg_state state = otg->state;
 	u8 flag;
 	int retval;
+	struct otg_hcd_ops *hcd_ops = otg->hcd_ops;
 
 	if (state != OTG_STATE_A_HOST && state != OTG_STATE_B_HOST)
 		return;
 
-	udev = usb_hub_find_child(otg->host->root_hub, 1);
+	if (!hcd_ops || !hcd_ops->usb_control_msg ||
+	    !hcd_ops->usb_hub_find_child)
+		return;
+
+	udev = hcd_ops->usb_hub_find_child(otg->host->root_hub, 1);
 	if (!udev) {
 		dev_err(otg->host->controller,
 			"no usb dev connected, can't start HNP polling\n");
@@ -154,7 +159,7 @@ static void otg_hnp_polling_work(struct work_struct *work)
 
 	*fsm->host_req_flag = 0;
 	/* Get host request flag from connected USB device */
-	retval = usb_control_msg(udev,
+	retval = hcd_ops->usb_control_msg(udev,
 				usb_rcvctrlpipe(udev, 0),
 				USB_REQ_GET_STATUS,
 				USB_DIR_IN | USB_RECIP_DEVICE,
@@ -183,7 +188,7 @@ static void otg_hnp_polling_work(struct work_struct *work)
 	if (state == OTG_STATE_A_HOST) {
 		/* Set b_hnp_enable */
 		if (!otg->host->b_hnp_enable) {
-			retval = usb_control_msg(udev,
+			retval = hcd_ops->usb_control_msg(udev,
 					usb_sndctrlpipe(udev, 0),
 					USB_REQ_SET_FEATURE, 0,
 					USB_DEVICE_B_HNP_ENABLE,
@@ -262,7 +267,9 @@ static int otg_set_state(struct otg_fsm *fsm, enum usb_otg_state new_state)
 		otg_loc_conn(otg, 0);
 		otg_loc_sof(otg, 1);
 		otg_set_protocol(fsm, PROTO_HOST);
-		usb_bus_start_enum(otg->host, otg->host->otg_port);
+		if (otg->hcd_ops && otg->hcd_ops->usb_bus_start_enum)
+			otg->hcd_ops->usb_bus_start_enum(otg->host,
+							 otg->host->otg_port);
 		otg_start_hnp_polling(fsm);
 		break;
 	case OTG_STATE_A_IDLE:
diff --git a/drivers/usb/phy/phy-fsl-usb.c b/drivers/usb/phy/phy-fsl-usb.c
index 587a187..9dbd9f0 100644
--- a/drivers/usb/phy/phy-fsl-usb.c
+++ b/drivers/usb/phy/phy-fsl-usb.c
@@ -792,6 +792,12 @@ static struct otg_fsm_ops fsl_otg_ops = {
 	.start_gadget = fsl_otg_start_gadget,
 };
 
+static struct otg_hcd_ops fsl_hcd_ops = {
+	.usb_bus_start_enum = usb_bus_start_enum,
+	.usb_control_msg = usb_control_msg,
+	.usb_hub_find_child = usb_hub_find_child,
+};
+
 /* Initialize the global variable fsl_otg_dev and request IRQ for OTG */
 static int fsl_otg_conf(struct platform_device *pdev)
 {
@@ -820,6 +826,7 @@ static int fsl_otg_conf(struct platform_device *pdev)
 
 	/* Set OTG state machine operations */
 	fsl_otg_tc->otg.fsm.ops = &fsl_otg_ops;
+	fsl_otg_tc->otg.hcd_ops = &fsl_hcd_ops;
 
 	/* initialize the otg structure */
 	fsl_otg_tc->phy.label = DRIVER_DESC;
diff --git a/include/linux/usb/otg.h b/include/linux/usb/otg.h
index e8a14dc..85b8fb5 100644
--- a/include/linux/usb/otg.h
+++ b/include/linux/usb/otg.h
@@ -12,6 +12,7 @@
 #include <linux/phy/phy.h>
 #include <linux/usb/phy.h>
 #include <linux/usb/otg-fsm.h>
+#include <linux/usb/hcd.h>
 
 struct usb_otg {
 	u8			default_a;
@@ -24,6 +25,7 @@ struct usb_otg {
 
 	enum usb_otg_state	state;
 	struct otg_fsm fsm;
+	struct otg_hcd_ops	*hcd_ops;
 
 	/* bind/unbind the host controller */
 	int	(*set_host)(struct usb_otg *otg, struct usb_bus *host);
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH v8 06/14] usb: gadget.h: Add OTG to gadget interface
  2016-05-13 10:03 [PATCH v8 00/14] USB OTG/dual-role framework Roger Quadros
                   ` (4 preceding siblings ...)
  2016-05-13 10:03 ` [PATCH v8 05/14] usb: otg-fsm: move host controller operations into usb_otg->hcd_ops Roger Quadros
@ 2016-05-13 10:03 ` Roger Quadros
  2016-05-13 10:03 ` [PATCH v8 07/14] usb: otg: get rid of CONFIG_USB_OTG_FSM in favour of CONFIG_USB_OTG Roger Quadros
                   ` (8 subsequent siblings)
  14 siblings, 0 replies; 62+ messages in thread
From: Roger Quadros @ 2016-05-13 10:03 UTC (permalink / raw)
  To: peter.chen
  Cc: balbi, tony, gregkh, dan.j.williams, mathias.nyman, Joao.Pinto,
	sergei.shtylyov, jun.li, grygorii.strashko, yoshihiro.shimoda.uh,
	robh, nsekhar, b-liu, linux-usb, linux-omap, linux-kernel,
	devicetree, Roger Quadros

The OTG core will use struct otg_gadget_ops to
start/stop the gadget controller.

The main purpose of this interface is to avoid directly
calling usb_gadget_start/stop() from the OTG core as they
wouldn't be defined in the built-in symbol table if
CONFIG_USB_GADGET is m.

Signed-off-by: Roger Quadros <rogerq@ti.com>
---
 include/linux/usb/gadget.h | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h
index 5d4e151..20a2f8a 100644
--- a/include/linux/usb/gadget.h
+++ b/include/linux/usb/gadget.h
@@ -1100,6 +1100,22 @@ struct usb_gadget_driver {
 };
 
 
+/*-------------------------------------------------------------------------*/
+
+/**
+ * struct otg_gadget_ops - Interface between OTG core and gadget
+ *
+ * Provided by the gadget core to allow the OTG core to start/stop the gadget
+ *
+ * @start: function to start the gadget
+ * @stop: function to stop the gadget
+ * @connect_control: function to connect/disconnect from the bus
+ */
+struct otg_gadget_ops {
+	int (*start)(struct usb_gadget *gadget);
+	int (*stop)(struct usb_gadget *gadget);
+	int (*connect_control)(struct usb_gadget *gadget, bool connect);
+};
 
 /*-------------------------------------------------------------------------*/
 
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH v8 07/14] usb: otg: get rid of CONFIG_USB_OTG_FSM in favour of CONFIG_USB_OTG
  2016-05-13 10:03 [PATCH v8 00/14] USB OTG/dual-role framework Roger Quadros
                   ` (5 preceding siblings ...)
  2016-05-13 10:03 ` [PATCH v8 06/14] usb: gadget.h: Add OTG to gadget interface Roger Quadros
@ 2016-05-13 10:03 ` Roger Quadros
  2016-05-13 10:03 ` [PATCH v8 08/14] usb: otg: add OTG/dual-role core Roger Quadros
                   ` (7 subsequent siblings)
  14 siblings, 0 replies; 62+ messages in thread
From: Roger Quadros @ 2016-05-13 10:03 UTC (permalink / raw)
  To: peter.chen
  Cc: balbi, tony, gregkh, dan.j.williams, mathias.nyman, Joao.Pinto,
	sergei.shtylyov, jun.li, grygorii.strashko, yoshihiro.shimoda.uh,
	robh, nsekhar, b-liu, linux-usb, linux-omap, linux-kernel,
	devicetree, Roger Quadros

Let's use CONFIG_USB_OTG as a single config option to enable
USB OTG and the OTG FSM. This makes things a lot less confusing.

Update all users of CONFIG_USB_OTG_FSM to CONFIG_USB_OTG.

Signed-off-by: Roger Quadros <rogerq@ti.com>
Acked-by: Peter Chen <peter.chen@nxp.com>
---
 Documentation/usb/chipidea.txt | 2 +-
 drivers/usb/chipidea/Makefile  | 2 +-
 drivers/usb/chipidea/ci.h      | 2 +-
 drivers/usb/chipidea/otg_fsm.h | 2 +-
 drivers/usb/common/Makefile    | 3 ++-
 drivers/usb/core/Kconfig       | 8 --------
 drivers/usb/phy/Kconfig        | 2 +-
 7 files changed, 7 insertions(+), 14 deletions(-)

diff --git a/Documentation/usb/chipidea.txt b/Documentation/usb/chipidea.txt
index 678741b..3b1f263 100644
--- a/Documentation/usb/chipidea.txt
+++ b/Documentation/usb/chipidea.txt
@@ -5,7 +5,7 @@ with 2 Freescale i.MX6Q sabre SD boards.
 
 1.1 How to enable OTG FSM in menuconfig
 ---------------------------------------
-Select CONFIG_USB_OTG_FSM, rebuild kernel Image and modules.
+Select CONFIG_USB_OTG, rebuild kernel Image and modules.
 If you want to check some internal variables for otg fsm,
 mount debugfs, there are 2 files which can show otg fsm
 variables and some controller registers value:
diff --git a/drivers/usb/chipidea/Makefile b/drivers/usb/chipidea/Makefile
index 518e445..45aa24d 100644
--- a/drivers/usb/chipidea/Makefile
+++ b/drivers/usb/chipidea/Makefile
@@ -3,7 +3,7 @@ obj-$(CONFIG_USB_CHIPIDEA)		+= ci_hdrc.o
 ci_hdrc-y				:= core.o otg.o debug.o
 ci_hdrc-$(CONFIG_USB_CHIPIDEA_UDC)	+= udc.o
 ci_hdrc-$(CONFIG_USB_CHIPIDEA_HOST)	+= host.o
-ci_hdrc-$(CONFIG_USB_OTG_FSM)		+= otg_fsm.o
+ci_hdrc-$(CONFIG_USB_OTG)		+= otg_fsm.o
 
 # Glue/Bridge layers go here
 
diff --git a/drivers/usb/chipidea/ci.h b/drivers/usb/chipidea/ci.h
index c523975..1a32b8c 100644
--- a/drivers/usb/chipidea/ci.h
+++ b/drivers/usb/chipidea/ci.h
@@ -406,7 +406,7 @@ static inline u32 hw_test_and_write(struct ci_hdrc *ci, enum ci_hw_regs reg,
  */
 static inline bool ci_otg_is_fsm_mode(struct ci_hdrc *ci)
 {
-#ifdef CONFIG_USB_OTG_FSM
+#ifdef CONFIG_USB_OTG
 	struct usb_otg_caps *otg_caps = &ci->platdata->ci_otg_caps;
 
 	return ci->is_otg && ci->roles[CI_ROLE_HOST] &&
diff --git a/drivers/usb/chipidea/otg_fsm.h b/drivers/usb/chipidea/otg_fsm.h
index 6366fe3..2d451bb 100644
--- a/drivers/usb/chipidea/otg_fsm.h
+++ b/drivers/usb/chipidea/otg_fsm.h
@@ -64,7 +64,7 @@
 
 #define TB_AIDL_BDIS         (20)	/* 4ms ~ 150ms, section 5.2.1 */
 
-#if IS_ENABLED(CONFIG_USB_OTG_FSM)
+#if IS_ENABLED(CONFIG_USB_OTG)
 
 int ci_hdrc_otg_fsm_init(struct ci_hdrc *ci);
 int ci_otg_fsm_work(struct ci_hdrc *ci);
diff --git a/drivers/usb/common/Makefile b/drivers/usb/common/Makefile
index 6bbb3ec..f8f2c88 100644
--- a/drivers/usb/common/Makefile
+++ b/drivers/usb/common/Makefile
@@ -6,5 +6,6 @@ obj-$(CONFIG_USB_COMMON)	  += usb-common.o
 usb-common-y			  += common.o
 usb-common-$(CONFIG_USB_LED_TRIG) += led.o
 
-obj-$(CONFIG_USB_OTG_FSM) += usb-otg-fsm.o
 obj-$(CONFIG_USB_ULPI_BUS)	+= ulpi.o
+usbotg-y		:= usb-otg-fsm.o
+obj-$(CONFIG_USB_OTG)	+= usbotg.o
diff --git a/drivers/usb/core/Kconfig b/drivers/usb/core/Kconfig
index dd28010..ae228d0 100644
--- a/drivers/usb/core/Kconfig
+++ b/drivers/usb/core/Kconfig
@@ -75,14 +75,6 @@ config USB_OTG_BLACKLIST_HUB
 	  and software costs by not supporting external hubs.  So
 	  are "Embedded Hosts" that don't offer OTG support.
 
-config USB_OTG_FSM
-	tristate "USB 2.0 OTG FSM implementation"
-	depends on USB && USB_OTG
-	select USB_PHY
-	help
-	  Implements OTG Finite State Machine as specified in On-The-Go
-	  and Embedded Host Supplement to the USB Revision 2.0 Specification.
-
 config USB_ULPI_BUS
 	tristate "USB ULPI PHY interface support"
 	depends on USB_SUPPORT
diff --git a/drivers/usb/phy/Kconfig b/drivers/usb/phy/Kconfig
index c690474..06794e2 100644
--- a/drivers/usb/phy/Kconfig
+++ b/drivers/usb/phy/Kconfig
@@ -20,7 +20,7 @@ config AB8500_USB
 
 config FSL_USB2_OTG
 	bool "Freescale USB OTG Transceiver Driver"
-	depends on USB_EHCI_FSL && USB_FSL_USB2 && USB_OTG_FSM && PM
+	depends on USB_EHCI_FSL && USB_FSL_USB2 && USB_OTG && PM
 	select USB_PHY
 	help
 	  Enable this to support Freescale USB OTG transceiver.
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH v8 08/14] usb: otg: add OTG/dual-role core
  2016-05-13 10:03 [PATCH v8 00/14] USB OTG/dual-role framework Roger Quadros
                   ` (6 preceding siblings ...)
  2016-05-13 10:03 ` [PATCH v8 07/14] usb: otg: get rid of CONFIG_USB_OTG_FSM in favour of CONFIG_USB_OTG Roger Quadros
@ 2016-05-13 10:03 ` Roger Quadros
  2016-05-16  9:00   ` Roger Quadros
  2016-05-24  9:45   ` Roger Quadros
  2016-05-13 10:03 ` [PATCH v8 09/14] usb: of: add an API to get OTG device from USB controller node Roger Quadros
                   ` (6 subsequent siblings)
  14 siblings, 2 replies; 62+ messages in thread
From: Roger Quadros @ 2016-05-13 10:03 UTC (permalink / raw)
  To: peter.chen
  Cc: balbi, tony, gregkh, dan.j.williams, mathias.nyman, Joao.Pinto,
	sergei.shtylyov, jun.li, grygorii.strashko, yoshihiro.shimoda.uh,
	robh, nsekhar, b-liu, linux-usb, linux-omap, linux-kernel,
	devicetree, Roger Quadros

It provides APIs for the following tasks

- Registering an OTG/dual-role capable controller
- Registering Host and Gadget controllers to OTG core
- Providing inputs to and kicking the OTG state machine

Provide a dual-role device (DRD) state machine.
DRD mode is a reduced functionality OTG mode. In this mode
we don't support SRP, HNP and dynamic role-swap.

In DRD operation, the controller mode (Host or Peripheral)
is decided based on the ID pin status. Once a cable plug (Type-A
or Type-B) is attached the controller selects the state
and doesn't change till the cable in unplugged and a different
cable type is inserted.

As we don't need most of the complex OTG states and OTG timers
we implement a lean DRD state machine in usb-otg.c.
The DRD state machine is only interested in 2 hardware inputs
'id' and 'b_sess_vld'.

Signed-off-by: Roger Quadros <rogerq@ti.com>
---
 drivers/usb/common/Makefile  |    2 +-
 drivers/usb/common/usb-otg.c | 1042 ++++++++++++++++++++++++++++++++++++++++++
 drivers/usb/core/Kconfig     |    4 +-
 include/linux/usb/gadget.h   |    2 +
 include/linux/usb/hcd.h      |    1 +
 include/linux/usb/otg-fsm.h  |    7 +
 include/linux/usb/otg.h      |  154 ++++++-
 7 files changed, 1206 insertions(+), 6 deletions(-)
 create mode 100644 drivers/usb/common/usb-otg.c

diff --git a/drivers/usb/common/Makefile b/drivers/usb/common/Makefile
index f8f2c88..730d928 100644
--- a/drivers/usb/common/Makefile
+++ b/drivers/usb/common/Makefile
@@ -7,5 +7,5 @@ usb-common-y			  += common.o
 usb-common-$(CONFIG_USB_LED_TRIG) += led.o
 
 obj-$(CONFIG_USB_ULPI_BUS)	+= ulpi.o
-usbotg-y		:= usb-otg-fsm.o
+usbotg-y		:= usb-otg.o usb-otg-fsm.o
 obj-$(CONFIG_USB_OTG)	+= usbotg.o
diff --git a/drivers/usb/common/usb-otg.c b/drivers/usb/common/usb-otg.c
new file mode 100644
index 0000000..64be6df
--- /dev/null
+++ b/drivers/usb/common/usb-otg.c
@@ -0,0 +1,1042 @@
+/**
+ * drivers/usb/common/usb-otg.c - USB OTG core
+ *
+ * Copyright (C) 2016 Texas Instruments Incorporated - http://www.ti.com
+ * Author: Roger Quadros <rogerq@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/usb/otg.h>
+#include <linux/usb/gadget.h>
+#include <linux/workqueue.h>
+
+struct otg_gcd {
+	struct usb_gadget *gadget;
+	struct otg_gadget_ops *ops;
+};
+
+/* OTG device list */
+LIST_HEAD(otg_list);
+static DEFINE_MUTEX(otg_list_mutex);
+
+/* Hosts and Gadgets waiting for OTG controller */
+struct otg_wait_data {
+	struct device *dev;		/* OTG controller device */
+
+	struct otg_hcd primary_hcd;
+	struct otg_hcd shared_hcd;
+	struct otg_gcd gcd;
+	struct list_head list;
+};
+
+LIST_HEAD(wait_list);
+static DEFINE_MUTEX(wait_list_mutex);
+
+static int usb_otg_hcd_is_primary_hcd(struct usb_hcd *hcd)
+{
+	if (!hcd->primary_hcd)
+		return 1;
+	return hcd == hcd->primary_hcd;
+}
+
+/**
+ * Check if the OTG device is in our wait list and return
+ * otg_wait_data, else NULL.
+ *
+ * wait_list_mutex must be held.
+ */
+static struct otg_wait_data *usb_otg_get_wait(struct device *otg_dev)
+{
+	struct otg_wait_data *wait;
+
+	if (!otg_dev)
+		return NULL;
+
+	/* is there an entry for this otg_dev ?*/
+	list_for_each_entry(wait, &wait_list, list) {
+		if (wait->dev == otg_dev)
+			return wait;
+	}
+
+	return NULL;
+}
+
+/**
+ * Add the hcd to our wait list
+ */
+static int usb_otg_hcd_wait_add(struct device *otg_dev, struct usb_hcd *hcd,
+				unsigned int irqnum, unsigned long irqflags,
+				struct otg_hcd_ops *ops)
+{
+	struct otg_wait_data *wait;
+	int ret = -EINVAL;
+
+	mutex_lock(&wait_list_mutex);
+
+	wait = usb_otg_get_wait(otg_dev);
+	if (!wait) {
+		/* Not yet in wait list? allocate and add */
+		wait = kzalloc(sizeof(*wait), GFP_KERNEL);
+		if (!wait) {
+			ret = -ENOMEM;
+			goto fail;
+		}
+
+		wait->dev = otg_dev;
+		list_add_tail(&wait->list, &wait_list);
+	}
+
+	if (usb_otg_hcd_is_primary_hcd(hcd)) {
+		if (wait->primary_hcd.hcd)	/* already assigned? */
+			goto fail;
+
+		wait->primary_hcd.hcd = hcd;
+		wait->primary_hcd.irqnum = irqnum;
+		wait->primary_hcd.irqflags = irqflags;
+		wait->primary_hcd.ops = ops;
+		wait->primary_hcd.otg_dev = otg_dev;
+	} else {
+		if (wait->shared_hcd.hcd)	/* already assigned? */
+			goto fail;
+
+		wait->shared_hcd.hcd = hcd;
+		wait->shared_hcd.irqnum = irqnum;
+		wait->shared_hcd.irqflags = irqflags;
+		wait->shared_hcd.ops = ops;
+		wait->shared_hcd.otg_dev = otg_dev;
+	}
+
+	mutex_unlock(&wait_list_mutex);
+	return 0;
+
+fail:
+	mutex_unlock(&wait_list_mutex);
+	return ret;
+}
+
+/**
+ * Check and free wait list entry if empty
+ *
+ * wait_list_mutex must be held
+ */
+static void usb_otg_check_free_wait(struct otg_wait_data *wait)
+{
+	if (wait->primary_hcd.hcd || wait->shared_hcd.hcd || wait->gcd.gadget)
+		return;
+
+	list_del(&wait->list);
+	kfree(wait);
+}
+
+/**
+ * Remove the hcd from our wait list
+ */
+static int usb_otg_hcd_wait_remove(struct usb_hcd *hcd)
+{
+	struct otg_wait_data *wait;
+
+	mutex_lock(&wait_list_mutex);
+
+	/* is there an entry for this hcd ?*/
+	list_for_each_entry(wait, &wait_list, list) {
+		if (wait->primary_hcd.hcd == hcd) {
+			wait->primary_hcd.hcd = 0;
+			goto found;
+		} else if (wait->shared_hcd.hcd == hcd) {
+			wait->shared_hcd.hcd = 0;
+			goto found;
+		}
+	}
+
+	mutex_unlock(&wait_list_mutex);
+	return -EINVAL;
+
+found:
+	usb_otg_check_free_wait(wait);
+	mutex_unlock(&wait_list_mutex);
+
+	return 0;
+}
+
+/**
+ * Add the gadget to our wait list
+ */
+static int usb_otg_gadget_wait_add(struct device *otg_dev,
+				   struct usb_gadget *gadget,
+				   struct otg_gadget_ops *ops)
+{
+	struct otg_wait_data *wait;
+	int ret = -EINVAL;
+
+	mutex_lock(&wait_list_mutex);
+
+	wait = usb_otg_get_wait(otg_dev);
+	if (!wait) {
+		/* Not yet in wait list? allocate and add */
+		wait = kzalloc(sizeof(*wait), GFP_KERNEL);
+		if (!wait) {
+			ret = -ENOMEM;
+			goto fail;
+		}
+
+		wait->dev = otg_dev;
+		list_add_tail(&wait->list, &wait_list);
+	}
+
+	if (wait->gcd.gadget) /* already assigned? */
+		goto fail;
+
+	wait->gcd.gadget = gadget;
+	wait->gcd.ops = ops;
+	mutex_unlock(&wait_list_mutex);
+
+	return 0;
+
+fail:
+	mutex_unlock(&wait_list_mutex);
+	return ret;
+}
+
+/**
+ * Remove the gadget from our wait list
+ */
+static int usb_otg_gadget_wait_remove(struct usb_gadget *gadget)
+{
+	struct otg_wait_data *wait;
+
+	mutex_lock(&wait_list_mutex);
+
+	/* is there an entry for this gadget ?*/
+	list_for_each_entry(wait, &wait_list, list) {
+		if (wait->gcd.gadget == gadget) {
+			wait->gcd.gadget = 0;
+			goto found;
+		}
+	}
+
+	mutex_unlock(&wait_list_mutex);
+
+	return -EINVAL;
+
+found:
+	usb_otg_check_free_wait(wait);
+	mutex_unlock(&wait_list_mutex);
+
+	return 0;
+}
+
+/**
+ * Register pending host/gadget and remove entry from wait list
+ */
+static void usb_otg_flush_wait(struct device *otg_dev)
+{
+	struct otg_wait_data *wait;
+	struct otg_hcd *whcd;
+	struct otg_gcd *wgcd;
+
+	mutex_lock(&wait_list_mutex);
+
+	wait = usb_otg_get_wait(otg_dev);
+	if (!wait)
+		goto done;
+
+	dev_dbg(otg_dev, "otg: registering pending host/gadget\n");
+	wgcd = &wait->gcd;
+	if (wgcd->gadget)
+		usb_otg_register_gadget(wgcd->gadget, wgcd->ops);
+
+	whcd = &wait->primary_hcd;
+	if (whcd->hcd)
+		usb_otg_register_hcd(whcd->hcd, whcd->irqnum, whcd->irqflags,
+				     whcd->ops);
+
+	whcd = &wait->shared_hcd;
+	if (whcd->hcd)
+		usb_otg_register_hcd(whcd->hcd, whcd->irqnum, whcd->irqflags,
+				     whcd->ops);
+
+	list_del(&wait->list);
+	kfree(wait);
+
+done:
+	mutex_unlock(&wait_list_mutex);
+}
+
+/**
+ * Check if the OTG device is in our OTG list and return
+ * usb_otg data, else NULL.
+ *
+ * otg_list_mutex must be held.
+ */
+static struct usb_otg *usb_otg_get_data(struct device *otg_dev)
+{
+	struct usb_otg *otg;
+
+	if (!otg_dev)
+		return NULL;
+
+	list_for_each_entry(otg, &otg_list, list) {
+		if (otg->dev == otg_dev)
+			return otg;
+	}
+
+	return NULL;
+}
+
+/**
+ * usb_otg_start_host - start/stop the host controller
+ * @otg:	usb_otg instance
+ * @on:		true to start, false to stop
+ *
+ * Start/stop the USB host controller. This function is meant
+ * for use by the OTG controller driver.
+ */
+int usb_otg_start_host(struct usb_otg *otg, int on)
+{
+	struct otg_hcd_ops *hcd_ops = otg->hcd_ops;
+
+	dev_dbg(otg->dev, "otg: %s %d\n", __func__, on);
+	if (!otg->host) {
+		WARN_ONCE(1, "otg: fsm running without host\n");
+		return 0;
+	}
+
+	if (on) {
+		if (otg->flags & OTG_FLAG_HOST_RUNNING)
+			return 0;
+
+		otg->flags |= OTG_FLAG_HOST_RUNNING;
+
+		/* start host */
+		hcd_ops->add(otg->primary_hcd.hcd, otg->primary_hcd.irqnum,
+			     otg->primary_hcd.irqflags);
+		if (otg->shared_hcd.hcd) {
+			hcd_ops->add(otg->shared_hcd.hcd,
+				     otg->shared_hcd.irqnum,
+				     otg->shared_hcd.irqflags);
+		}
+	} else {
+		if (!(otg->flags & OTG_FLAG_HOST_RUNNING))
+			return 0;
+
+		otg->flags &= ~OTG_FLAG_HOST_RUNNING;
+
+		/* stop host */
+		if (otg->shared_hcd.hcd)
+			hcd_ops->remove(otg->shared_hcd.hcd);
+
+		hcd_ops->remove(otg->primary_hcd.hcd);
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(usb_otg_start_host);
+
+/**
+ * usb_otg_start_gadget - start/stop the gadget controller
+ * @otg:	usb_otg instance
+ * @on:		true to start, false to stop
+ *
+ * Start/stop the USB gadget controller. This function is meant
+ * for use by the OTG controller driver.
+ */
+int usb_otg_start_gadget(struct usb_otg *otg, int on)
+{
+	struct usb_gadget *gadget = otg->gadget;
+
+	dev_dbg(otg->dev, "otg: %s %d\n", __func__, on);
+	if (!gadget) {
+		WARN_ONCE(1, "otg: fsm running without gadget\n");
+		return 0;
+	}
+
+	if (on) {
+		if (otg->flags & OTG_FLAG_GADGET_RUNNING)
+			return 0;
+
+		otg->flags |= OTG_FLAG_GADGET_RUNNING;
+		otg->gadget_ops->start(otg->gadget);
+	} else {
+		if (!(otg->flags & OTG_FLAG_GADGET_RUNNING))
+			return 0;
+
+		otg->flags &= ~OTG_FLAG_GADGET_RUNNING;
+		otg->gadget_ops->stop(otg->gadget);
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(usb_otg_start_gadget);
+
+/**
+ * Change USB protocol when there is a protocol change.
+ * fsm->lock must be held.
+ */
+static int drd_set_protocol(struct otg_fsm *fsm, int protocol)
+{
+	struct usb_otg *otg = container_of(fsm, struct usb_otg, fsm);
+	int ret = 0;
+
+	if (fsm->protocol != protocol) {
+		dev_dbg(otg->dev, "otg: changing role fsm->protocol= %d; new protocol= %d\n",
+			fsm->protocol, protocol);
+		/* stop old protocol */
+		if (fsm->protocol == PROTO_HOST) {
+			ret = otg_start_host(otg, 0);
+		} else if (fsm->protocol == PROTO_GADGET) {
+			otg->gadget_ops->connect_control(otg->gadget, false);
+			ret = otg_start_gadget(otg, 0);
+		}
+
+		if (ret)
+			return ret;
+
+		/* start new protocol */
+		if (protocol == PROTO_HOST) {
+			ret = otg_start_host(otg, 1);
+		} else if (protocol == PROTO_GADGET) {
+			ret = otg_start_gadget(otg, 1);
+			otg->gadget_ops->connect_control(otg->gadget, true);
+		}
+
+		if (ret)
+			return ret;
+
+		fsm->protocol = protocol;
+		return 0;
+	}
+
+	return 0;
+}
+
+/**
+ * Called when entering a DRD state.
+ * fsm->lock must be held.
+ */
+static void drd_set_state(struct otg_fsm *fsm, enum usb_otg_state new_state)
+{
+	struct usb_otg *otg = container_of(fsm, struct usb_otg, fsm);
+
+	if (otg->state == new_state)
+		return;
+
+	fsm->state_changed = 1;
+	dev_dbg(otg->dev, "otg: set state: %s\n",
+		usb_otg_state_string(new_state));
+	switch (new_state) {
+	case OTG_STATE_B_IDLE:
+		drd_set_protocol(fsm, PROTO_UNDEF);
+		otg_drv_vbus(otg, 0);
+		break;
+	case OTG_STATE_B_PERIPHERAL:
+		drd_set_protocol(fsm, PROTO_GADGET);
+		otg_drv_vbus(otg, 0);
+		break;
+	case OTG_STATE_A_HOST:
+		drd_set_protocol(fsm, PROTO_HOST);
+		otg_drv_vbus(otg, 1);
+		break;
+	default:
+		dev_warn(otg->dev, "%s: otg: invalid state: %s\n",
+			 __func__, usb_otg_state_string(new_state));
+		break;
+	}
+
+	otg->state = new_state;
+}
+
+/**
+ * DRD state change judgement
+ *
+ * For DRD we're only interested in some of the OTG states
+ * i.e. OTG_STATE_B_IDLE: both peripheral and host are stopped
+ *	OTG_STATE_B_PERIPHERAL: peripheral active
+ *	OTG_STATE_A_HOST: host active
+ * we're only interested in the following inputs
+ *	fsm->id, fsm->b_sess_vld
+ */
+int drd_statemachine(struct usb_otg *otg)
+{
+	struct otg_fsm *fsm = &otg->fsm;
+	enum usb_otg_state state;
+	int ret;
+
+	mutex_lock(&fsm->lock);
+
+	fsm->state_changed = 0;
+	state = otg->state;
+
+	switch (state) {
+	case OTG_STATE_UNDEFINED:
+		if (!fsm->id)
+			drd_set_state(fsm, OTG_STATE_A_HOST);
+		else if (fsm->id && fsm->b_sess_vld)
+			drd_set_state(fsm, OTG_STATE_B_PERIPHERAL);
+		else
+			drd_set_state(fsm, OTG_STATE_B_IDLE);
+		break;
+	case OTG_STATE_B_IDLE:
+		if (!fsm->id)
+			drd_set_state(fsm, OTG_STATE_A_HOST);
+		else if (fsm->b_sess_vld)
+			drd_set_state(fsm, OTG_STATE_B_PERIPHERAL);
+		break;
+	case OTG_STATE_B_PERIPHERAL:
+		if (!fsm->id)
+			drd_set_state(fsm, OTG_STATE_A_HOST);
+		else if (!fsm->b_sess_vld)
+			drd_set_state(fsm, OTG_STATE_B_IDLE);
+		break;
+	case OTG_STATE_A_HOST:
+		if (fsm->id && fsm->b_sess_vld)
+			drd_set_state(fsm, OTG_STATE_B_PERIPHERAL);
+		else if (fsm->id && !fsm->b_sess_vld)
+			drd_set_state(fsm, OTG_STATE_B_IDLE);
+		break;
+
+	default:
+		dev_err(otg->dev, "%s: otg: invalid usb-drd state: %s\n",
+			__func__, usb_otg_state_string(state));
+		break;
+	}
+
+	ret = fsm->state_changed;
+	mutex_unlock(&fsm->lock);
+	dev_dbg(otg->dev, "otg: quit statemachine, changed %d\n",
+		fsm->state_changed);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(drd_statemachine);
+
+/**
+ * Dual-role device (DRD) work function
+ */
+static void usb_drd_work(struct work_struct *work)
+{
+	struct usb_otg *otg = container_of(work, struct usb_otg, work);
+
+	pm_runtime_get_sync(otg->dev);
+	drd_statemachine(otg);
+	pm_runtime_put_sync(otg->dev);
+}
+
+/**
+ * usb_otg_register() - Register the OTG/dual-role device to OTG core
+ * @dev: OTG/dual-role controller device.
+ * @config: OTG configuration.
+ *
+ * Registers the OTG/dual-role controller device with the USB OTG core.
+ *
+ * Return: struct usb_otg * if success, ERR_PTR() if error.
+ */
+struct usb_otg *usb_otg_register(struct device *dev,
+				 struct usb_otg_config *config)
+{
+	struct usb_otg *otg;
+	struct otg_wait_data *wait;
+	int ret = 0;
+
+	if (!dev || !config || !config->fsm_ops)
+		return ERR_PTR(-EINVAL);
+
+	/* already in list? */
+	mutex_lock(&otg_list_mutex);
+	if (usb_otg_get_data(dev)) {
+		dev_err(dev, "otg: %s: device already in otg list\n",
+			__func__);
+		ret = -EINVAL;
+		goto unlock;
+	}
+
+	/* allocate and add to list */
+	otg = kzalloc(sizeof(*otg), GFP_KERNEL);
+	if (!otg) {
+		ret = -ENOMEM;
+		goto unlock;
+	}
+
+	otg->dev = dev;
+	otg->caps = config->otg_caps;
+
+	if ((otg->caps->hnp_support || otg->caps->srp_support ||
+	     otg->caps->adp_support) && !config->otg_work) {
+		dev_err(dev,
+			"otg: otg_work must be provided for OTG support\n");
+		ret = -EINVAL;
+		goto err_wq;
+	}
+
+	if (config->otg_work)	/* custom otg_work ? */
+		INIT_WORK(&otg->work, config->otg_work);
+	else
+		INIT_WORK(&otg->work, usb_drd_work);
+
+	otg->wq = create_freezable_workqueue("usb_otg");
+	if (!otg->wq) {
+		dev_err(dev, "otg: %s: can't create workqueue\n",
+			__func__);
+		ret = -ENOMEM;
+		goto err_wq;
+	}
+
+	/* set otg ops */
+	otg->fsm.ops = config->fsm_ops;
+
+	mutex_init(&otg->fsm.lock);
+
+	list_add_tail(&otg->list, &otg_list);
+	mutex_unlock(&otg_list_mutex);
+
+	/* were we in wait list? */
+	mutex_lock(&wait_list_mutex);
+	wait = usb_otg_get_wait(dev);
+	mutex_unlock(&wait_list_mutex);
+	if (wait) {
+		/* register pending host/gadget and flush from list */
+		usb_otg_flush_wait(dev);
+	}
+
+	return otg;
+
+err_wq:
+	kfree(otg);
+unlock:
+	mutex_unlock(&otg_list_mutex);
+	return ERR_PTR(ret);
+}
+EXPORT_SYMBOL_GPL(usb_otg_register);
+
+/**
+ * usb_otg_unregister() - Unregister the OTG/dual-role device from USB OTG core
+ * @dev: OTG controller device.
+ *
+ * Unregisters the OTG/dual-role controller device from USB OTG core.
+ * Prevents unregistering till both the associated Host and Gadget controllers
+ * have unregistered from the OTG core.
+ *
+ * Return: 0 on success, error value otherwise.
+ */
+int usb_otg_unregister(struct device *dev)
+{
+	struct usb_otg *otg;
+
+	mutex_lock(&otg_list_mutex);
+	otg = usb_otg_get_data(dev);
+	if (!otg) {
+		dev_err(dev, "otg: %s: device not in otg list\n",
+			__func__);
+		mutex_unlock(&otg_list_mutex);
+		return -EINVAL;
+	}
+
+	/* prevent unregister till both host & gadget have unregistered */
+	if (otg->host || otg->gadget) {
+		dev_err(dev, "otg: %s: host/gadget still registered\n",
+			__func__);
+		return -EBUSY;
+	}
+
+	/* OTG FSM is halted when host/gadget unregistered */
+	destroy_workqueue(otg->wq);
+
+	/* remove from otg list */
+	list_del(&otg->list);
+	kfree(otg);
+	mutex_unlock(&otg_list_mutex);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(usb_otg_unregister);
+
+/**
+ * start/kick the OTG FSM if we can
+ * fsm->lock must be held
+ */
+static void usb_otg_start_fsm(struct usb_otg *otg)
+{
+	struct otg_fsm *fsm = &otg->fsm;
+
+	if (fsm->running)
+		goto kick_fsm;
+
+	if (!otg->host) {
+		dev_info(otg->dev, "otg: can't start till host registers\n");
+		return;
+	}
+
+	if (!otg->gadget) {
+		dev_info(otg->dev, "otg: can't start till gadget registers\n");
+		return;
+	}
+
+	fsm->running = true;
+kick_fsm:
+	queue_work(otg->wq, &otg->work);
+}
+
+/**
+ * stop the OTG FSM. Stops Host & Gadget controllers as well.
+ * fsm->lock must be held
+ */
+static void usb_otg_stop_fsm(struct usb_otg *otg)
+{
+	struct otg_fsm *fsm = &otg->fsm;
+
+	if (!fsm->running)
+		return;
+
+	/* no more new events queued */
+	fsm->running = false;
+
+	flush_workqueue(otg->wq);
+	otg->state = OTG_STATE_UNDEFINED;
+
+	/* stop host/gadget immediately */
+	if (fsm->protocol == PROTO_HOST)
+		otg_start_host(otg, 0);
+	else if (fsm->protocol == PROTO_GADGET)
+		otg_start_gadget(otg, 0);
+	fsm->protocol = PROTO_UNDEF;
+}
+
+/**
+ * usb_otg_sync_inputs - Sync OTG inputs with the OTG state machine
+ * @fsm:	OTG FSM instance
+ *
+ * Used by the OTG driver to update the inputs to the OTG
+ * state machine.
+ *
+ * Can be called in IRQ context.
+ */
+void usb_otg_sync_inputs(struct usb_otg *otg)
+{
+	/* Don't kick FSM till it has started */
+	if (!otg->fsm.running)
+		return;
+
+	/* Kick FSM */
+	queue_work(otg->wq, &otg->work);
+}
+EXPORT_SYMBOL_GPL(usb_otg_sync_inputs);
+
+/**
+ * usb_otg_kick_fsm - Kick the OTG state machine
+ * @otg_dev:	OTG controller device
+ *
+ * Used by USB host/device stack to sync OTG related
+ * events to the OTG state machine.
+ * e.g. change in host_bus->b_hnp_enable, gadget->b_hnp_enable
+ *
+ * Returns: 0 on success, error value otherwise.
+ */
+int usb_otg_kick_fsm(struct device *otg_dev)
+{
+	struct usb_otg *otg;
+
+	mutex_lock(&otg_list_mutex);
+	otg = usb_otg_get_data(otg_dev);
+	mutex_unlock(&otg_list_mutex);
+	if (!otg) {
+		dev_dbg(otg_dev, "otg: %s: invalid otg device\n",
+			__func__);
+		return -ENODEV;
+	}
+
+	usb_otg_sync_inputs(otg);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(usb_otg_kick_fsm);
+
+/**
+ * usb_otg_register_hcd - Register the host controller to OTG core
+ * @hcd:	host controller device
+ * @irqnum:	interrupt number
+ * @irqflags:	interrupt flags
+ * @ops:	HCD ops to interface with the HCD
+ *
+ * This is used by the USB Host stack to register the host controller
+ * to the OTG core. Host controller must not be started by the
+ * caller as it is left upto the OTG state machine to do so.
+ * hcd->otg_dev must contain the related otg controller device.
+ *
+ * Returns: 0 on success, error value otherwise.
+ */
+int usb_otg_register_hcd(struct usb_hcd *hcd, unsigned int irqnum,
+			 unsigned long irqflags, struct otg_hcd_ops *ops)
+{
+	struct usb_otg *otg;
+	struct device *hcd_dev = hcd->self.controller;
+	struct device *otg_dev = hcd->otg_dev;
+
+	if (!otg_dev)
+		return -EINVAL;
+
+	/* we're otg but otg controller might not yet be registered */
+	mutex_lock(&otg_list_mutex);
+	otg = usb_otg_get_data(otg_dev);
+	mutex_unlock(&otg_list_mutex);
+	if (!otg) {
+		dev_dbg(hcd_dev,
+			"otg: controller not yet registered. waiting..\n");
+		/*
+		 * otg controller might register later. Put the hcd in
+		 * wait list and call us back when ready
+		 */
+		if (usb_otg_hcd_wait_add(otg_dev, hcd, irqnum, irqflags, ops)) {
+			dev_err(hcd_dev, "otg: failed to add hcd to wait list\n");
+			return -EINVAL;
+		}
+
+		return 0;
+	}
+
+	/* HCD will be started by OTG fsm when needed */
+	mutex_lock(&otg->fsm.lock);
+	if (otg->primary_hcd.hcd) {
+		/* probably a shared HCD ? */
+		if (usb_otg_hcd_is_primary_hcd(hcd)) {
+			dev_err(otg_dev, "otg: primary host already registered\n");
+			goto err;
+		}
+
+		if (hcd->shared_hcd == otg->primary_hcd.hcd) {
+			if (otg->shared_hcd.hcd) {
+				dev_err(otg_dev, "otg: shared host already registered\n");
+				goto err;
+			}
+
+			otg->shared_hcd.hcd = hcd;
+			otg->shared_hcd.irqnum = irqnum;
+			otg->shared_hcd.irqflags = irqflags;
+			otg->shared_hcd.ops = ops;
+			dev_info(otg_dev, "otg: shared host %s registered\n",
+				 dev_name(hcd->self.controller));
+		} else {
+			dev_err(otg_dev, "otg: invalid shared host %s\n",
+				dev_name(hcd->self.controller));
+			goto err;
+		}
+	} else {
+		if (!usb_otg_hcd_is_primary_hcd(hcd)) {
+			dev_err(otg_dev, "otg: primary host must be registered first\n");
+			goto err;
+		}
+
+		otg->primary_hcd.hcd = hcd;
+		otg->primary_hcd.irqnum = irqnum;
+		otg->primary_hcd.irqflags = irqflags;
+		otg->primary_hcd.ops = ops;
+		otg->hcd_ops = ops;
+		dev_info(otg_dev, "otg: primary host %s registered\n",
+			 dev_name(hcd->self.controller));
+	}
+
+	/*
+	 * we're ready only if we have shared HCD
+	 * or we don't need shared HCD.
+	 */
+	if (otg->shared_hcd.hcd || !otg->primary_hcd.hcd->shared_hcd) {
+		otg->host = hcd_to_bus(hcd);
+		/* FIXME: set bus->otg_port if this is true OTG port with HNP */
+
+		/* start FSM */
+		usb_otg_start_fsm(otg);
+	} else {
+		dev_dbg(otg_dev, "otg: can't start till shared host registers\n");
+	}
+
+	mutex_unlock(&otg->fsm.lock);
+
+	return 0;
+
+err:
+	mutex_unlock(&otg->fsm.lock);
+	return -EINVAL;
+}
+EXPORT_SYMBOL_GPL(usb_otg_register_hcd);
+
+/**
+ * usb_otg_unregister_hcd - Unregister the host controller from OTG core
+ * @hcd:	host controller device
+ *
+ * This is used by the USB Host stack to unregister the host controller
+ * from the OTG core. Ensures that host controller is not running
+ * on successful return.
+ *
+ * Returns: 0 on success, error value otherwise.
+ */
+int usb_otg_unregister_hcd(struct usb_hcd *hcd)
+{
+	struct usb_otg *otg;
+	struct device *hcd_dev = hcd_to_bus(hcd)->controller;
+	struct device *otg_dev = hcd->otg_dev;
+
+	if (!otg_dev)
+		return -EINVAL;	/* we're definitely not OTG */
+
+	mutex_lock(&otg_list_mutex);
+	otg = usb_otg_get_data(otg_dev);
+	mutex_unlock(&otg_list_mutex);
+	if (!otg) {
+		/* are we in wait list? */
+		if (!usb_otg_hcd_wait_remove(hcd))
+			return 0;
+
+		dev_dbg(hcd_dev, "otg: host wasn't registered with otg\n");
+		return -EINVAL;
+	}
+
+	mutex_lock(&otg->fsm.lock);
+	if (hcd == otg->primary_hcd.hcd) {
+		otg->primary_hcd.hcd = NULL;
+		dev_info(otg_dev, "otg: primary host %s unregistered\n",
+			 dev_name(hcd_dev));
+	} else if (hcd == otg->shared_hcd.hcd) {
+		otg->shared_hcd.hcd = NULL;
+		dev_info(otg_dev, "otg: shared host %s unregistered\n",
+			 dev_name(hcd_dev));
+	} else {
+		dev_err(otg_dev, "otg: host %s wasn't registered with otg\n",
+			dev_name(hcd_dev));
+		mutex_unlock(&otg->fsm.lock);
+		return -EINVAL;
+	}
+
+	/* stop FSM & Host */
+	usb_otg_stop_fsm(otg);
+	otg->host = NULL;
+
+	mutex_unlock(&otg->fsm.lock);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(usb_otg_unregister_hcd);
+
+/**
+ * usb_otg_register_gadget - Register the gadget controller to OTG core
+ * @gadget:	gadget controller
+ *
+ * This is used by the USB gadget stack to register the gadget controller
+ * to the OTG core. Gadget controller must not be started by the
+ * caller as it is left upto the OTG state machine to do so.
+ *
+ * Gadget core must call this only when all resources required for
+ * gadget controller to run are available.
+ * i.e. gadget function driver is available.
+ *
+ * Returns: 0 on success, error value otherwise.
+ */
+int usb_otg_register_gadget(struct usb_gadget *gadget,
+			    struct otg_gadget_ops *ops)
+{
+	struct usb_otg *otg;
+	struct device *gadget_dev = &gadget->dev;
+	struct device *otg_dev = gadget->otg_dev;
+
+	if (!otg_dev)
+		return -EINVAL;	/* we're definitely not OTG */
+
+	/* we're otg but otg controller might not yet be registered */
+	mutex_lock(&otg_list_mutex);
+	otg = usb_otg_get_data(otg_dev);
+	mutex_unlock(&otg_list_mutex);
+	if (!otg) {
+		dev_dbg(gadget_dev,
+			"otg: controller not yet registered. waiting..\n");
+		/*
+		 * otg controller might register later. Put the gadget in
+		 * wait list and call us back when ready
+		 */
+		if (usb_otg_gadget_wait_add(otg_dev, gadget, ops)) {
+			dev_err(gadget_dev,
+				"otg: failed to add to gadget to wait list\n");
+			return -EINVAL;
+		}
+
+		return 0;
+	}
+
+	mutex_lock(&otg->fsm.lock);
+	if (otg->gadget) {
+		dev_err(otg_dev, "otg: gadget already registered with otg\n");
+		mutex_unlock(&otg->fsm.lock);
+		return -EINVAL;
+	}
+
+	otg->gadget = gadget;
+	otg->gadget_ops = ops;
+	dev_info(otg_dev, "otg: gadget %s registered\n",
+		 dev_name(&gadget->dev));
+
+	/* start FSM */
+	usb_otg_start_fsm(otg);
+	mutex_unlock(&otg->fsm.lock);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(usb_otg_register_gadget);
+
+/**
+ * usb_otg_unregister_gadget - Unregister the gadget controller from OTG core
+ * @gadget:	gadget controller
+ *
+ * This is used by the USB gadget stack to unregister the gadget controller
+ * from the OTG core. Ensures that gadget controller is halted
+ * on successful return.
+ *
+ * Returns: 0 on success, error value otherwise.
+ */
+int usb_otg_unregister_gadget(struct usb_gadget *gadget)
+{
+	struct usb_otg *otg;
+	struct device *gadget_dev = &gadget->dev;
+	struct device *otg_dev = gadget->otg_dev;
+
+	if (!otg_dev)
+		return -EINVAL;
+
+	mutex_lock(&otg_list_mutex);
+	otg = usb_otg_get_data(otg_dev);
+	mutex_unlock(&otg_list_mutex);
+	if (!otg) {
+		/* are we in wait list? */
+		if (!usb_otg_gadget_wait_remove(gadget))
+			return 0;
+
+		dev_dbg(gadget_dev, "otg: gadget wasn't registered with otg\n");
+		return -EINVAL;
+	}
+
+	mutex_lock(&otg->fsm.lock);
+	if (otg->gadget != gadget) {
+		dev_err(otg_dev, "otg: gadget %s wasn't registered with otg\n",
+			dev_name(&gadget->dev));
+		mutex_unlock(&otg->fsm.lock);
+		return -EINVAL;
+	}
+
+	/* Stop FSM & gadget */
+	usb_otg_stop_fsm(otg);
+	otg->gadget = NULL;
+	mutex_unlock(&otg->fsm.lock);
+
+	dev_info(otg_dev, "otg: gadget %s unregistered\n",
+		 dev_name(&gadget->dev));
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(usb_otg_unregister_gadget);
diff --git a/drivers/usb/core/Kconfig b/drivers/usb/core/Kconfig
index ae228d0..de371e6 100644
--- a/drivers/usb/core/Kconfig
+++ b/drivers/usb/core/Kconfig
@@ -42,8 +42,8 @@ config USB_DYNAMIC_MINORS
 	  If you are unsure about this, say N here.
 
 config USB_OTG
-	bool "OTG support"
-	depends on PM
+	bool "OTG/Dual-role support"
+	depends on PM && USB_GADGET
 	default n
 	help
 	  The most notable feature of USB OTG is support for a
diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h
index 20a2f8a..3ecfddd 100644
--- a/include/linux/usb/gadget.h
+++ b/include/linux/usb/gadget.h
@@ -583,6 +583,7 @@ struct usb_gadget_ops {
  * @out_epnum: last used out ep number
  * @in_epnum: last used in ep number
  * @otg_caps: OTG capabilities of this gadget.
+ * @otg_dev: OTG controller device, if needs to be used with OTG core.
  * @sg_supported: true if we can handle scatter-gather
  * @is_otg: True if the USB device port uses a Mini-AB jack, so that the
  *	gadget driver must provide a USB OTG descriptor.
@@ -639,6 +640,7 @@ struct usb_gadget {
 	unsigned			out_epnum;
 	unsigned			in_epnum;
 	struct usb_otg_caps		*otg_caps;
+	struct device			*otg_dev;
 
 	unsigned			sg_supported:1;
 	unsigned			is_otg:1;
diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h
index 861ccaa..2017cd4 100644
--- a/include/linux/usb/hcd.h
+++ b/include/linux/usb/hcd.h
@@ -184,6 +184,7 @@ struct usb_hcd {
 	struct mutex		*bandwidth_mutex;
 	struct usb_hcd		*shared_hcd;
 	struct usb_hcd		*primary_hcd;
+	struct device		*otg_dev;	/* OTG controller device */
 
 
 #define HCD_BUFFER_POOLS	4
diff --git a/include/linux/usb/otg-fsm.h b/include/linux/usb/otg-fsm.h
index 26e6531..943714a 100644
--- a/include/linux/usb/otg-fsm.h
+++ b/include/linux/usb/otg-fsm.h
@@ -60,6 +60,11 @@ enum otg_fsm_timer {
 /**
  * struct otg_fsm - OTG state machine according to the OTG spec
  *
+ * DRD mode hardware Inputs
+ *
+ * @id:		TRUE for B-device, FALSE for A-device.
+ * @b_sess_vld:	VBUS voltage in regulation.
+ *
  * OTG hardware Inputs
  *
  *	Common inputs for A and B device
@@ -132,6 +137,7 @@ enum otg_fsm_timer {
  * a_clr_err:	Asserted (by application ?) to clear a_vbus_err due to an
  *		overcurrent condition and causes the A-device to transition
  *		to a_wait_vfall
+ * running:	state machine running/stopped indicator
  */
 struct otg_fsm {
 	/* Input */
@@ -187,6 +193,7 @@ struct otg_fsm {
 	int b_ase0_brst_tmout;
 	int a_bidl_adis_tmout;
 
+	bool running;
 	struct otg_fsm_ops *ops;
 
 	/* Current usb protocol used: 0:undefine; 1:host; 2:client */
diff --git a/include/linux/usb/otg.h b/include/linux/usb/otg.h
index 85b8fb5..b094352 100644
--- a/include/linux/usb/otg.h
+++ b/include/linux/usb/otg.h
@@ -10,10 +10,55 @@
 #define __LINUX_USB_OTG_H
 
 #include <linux/phy/phy.h>
-#include <linux/usb/phy.h>
-#include <linux/usb/otg-fsm.h>
+#include <linux/device.h>
+#include <linux/hrtimer.h>
+#include <linux/ktime.h>
+#include <linux/usb.h>
 #include <linux/usb/hcd.h>
+#include <linux/usb/gadget.h>
+#include <linux/usb/otg-fsm.h>
+#include <linux/usb/phy.h>
 
+/**
+ * struct otg_hcd - host controller state and interface
+ *
+ * @hcd: host controller
+ * @irqnum: irq number
+ * @irqflags: irq flags
+ * @ops: otg to host controller interface
+ * @ops: otg to host controller interface
+ * @otg_dev: otg controller device
+ */
+struct otg_hcd {
+	struct usb_hcd *hcd;
+	unsigned int irqnum;
+	unsigned long irqflags;
+	struct otg_hcd_ops *ops;
+	struct device *otg_dev;
+};
+
+/**
+ * struct usb_otg - usb otg controller state
+ *
+ * @default_a: Indicates we are an A device. i.e. Host.
+ * @phy: USB phy interface
+ * @usb_phy: old usb_phy interface
+ * @host: host controller bus
+ * @gadget: gadget device
+ * @state: current otg state
+ * @dev: otg controller device
+ * @caps: otg capabilities revision, hnp, srp, etc
+ * @fsm: otg finite state machine
+ * @hcd_ops: host controller interface
+ * ------- internal use only -------
+ * @primary_hcd: primary host state and interface
+ * @shared_hcd: shared host state and interface
+ * @gadget_ops: gadget controller interface
+ * @list: list of otg controllers
+ * @work: otg state machine work
+ * @wq: otg state machine work queue
+ * @flags: to track if host/gadget is running
+ */
 struct usb_otg {
 	u8			default_a;
 
@@ -24,9 +69,24 @@ struct usb_otg {
 	struct usb_gadget	*gadget;
 
 	enum usb_otg_state	state;
+	struct device *dev;
+	struct usb_otg_caps *caps;
 	struct otg_fsm fsm;
 	struct otg_hcd_ops	*hcd_ops;
 
+	/* internal use only */
+	struct otg_hcd primary_hcd;
+	struct otg_hcd shared_hcd;
+	struct otg_gadget_ops *gadget_ops;
+	struct list_head list;
+	struct work_struct work;
+	struct workqueue_struct *wq;
+	u32 flags;
+#define OTG_FLAG_GADGET_RUNNING (1 << 0)
+#define OTG_FLAG_HOST_RUNNING (1 << 1)
+	/* use otg->fsm.lock for serializing access */
+
+/*------------- deprecated interface -----------------------------*/
 	/* bind/unbind the host controller */
 	int	(*set_host)(struct usb_otg *otg, struct usb_bus *host);
 
@@ -42,7 +102,7 @@ struct usb_otg {
 
 	/* start or continue HNP role switch */
 	int	(*start_hnp)(struct usb_otg *otg);
-
+/*---------------------------------------------------------------*/
 };
 
 /**
@@ -60,8 +120,92 @@ struct usb_otg_caps {
 	bool adp_support;
 };
 
+/**
+ * struct usb_otg_config - otg controller configuration
+ * @caps: otg capabilities of the controller
+ * @ops: otg fsm operations
+ * @otg_work: optional custom otg state machine work function
+ */
+struct usb_otg_config {
+	struct usb_otg_caps *otg_caps;
+	struct otg_fsm_ops *fsm_ops;
+	void (*otg_work)(struct work_struct *work);
+};
+
 extern const char *usb_otg_state_string(enum usb_otg_state state);
 
+#if IS_ENABLED(CONFIG_USB_OTG)
+struct usb_otg *usb_otg_register(struct device *dev,
+				 struct usb_otg_config *config);
+int usb_otg_unregister(struct device *dev);
+int usb_otg_register_hcd(struct usb_hcd *hcd, unsigned int irqnum,
+			 unsigned long irqflags, struct otg_hcd_ops *ops);
+int usb_otg_unregister_hcd(struct usb_hcd *hcd);
+int usb_otg_register_gadget(struct usb_gadget *gadget,
+			    struct otg_gadget_ops *ops);
+int usb_otg_unregister_gadget(struct usb_gadget *gadget);
+void usb_otg_sync_inputs(struct usb_otg *otg);
+int usb_otg_kick_fsm(struct device *otg_dev);
+int usb_otg_start_host(struct usb_otg *otg, int on);
+int usb_otg_start_gadget(struct usb_otg *otg, int on);
+
+#else /* CONFIG_USB_OTG */
+
+static inline struct usb_otg *usb_otg_register(struct device *dev,
+					       struct usb_otg_config *config)
+{
+	return ERR_PTR(-ENOTSUPP);
+}
+
+static inline int usb_otg_unregister(struct device *dev)
+{
+	return -ENOTSUPP;
+}
+
+static inline int usb_otg_register_hcd(struct usb_hcd *hcd, unsigned int irqnum,
+				       unsigned long irqflags,
+				       struct otg_hcd_ops *ops)
+{
+	return -ENOTSUPP;
+}
+
+static inline int usb_otg_unregister_hcd(struct usb_hcd *hcd)
+{
+	return -ENOTSUPP;
+}
+
+static inline int usb_otg_register_gadget(struct usb_gadget *gadget,
+					  struct otg_gadget_ops *ops)
+{
+	return -ENOTSUPP;
+}
+
+static inline int usb_otg_unregister_gadget(struct usb_gadget *gadget)
+{
+	return -ENOTSUPP;
+}
+
+static inline void usb_otg_sync_inputs(struct usb_otg *otg)
+{
+}
+
+static inline int usb_otg_kick_fsm(struct device *otg_dev)
+{
+	return -ENOTSUPP;
+}
+
+static inline int usb_otg_start_host(struct usb_otg *otg, int on)
+{
+	return -ENOTSUPP;
+}
+
+static inline int usb_otg_start_gadget(struct usb_otg *otg, int on)
+{
+	return -ENOTSUPP;
+}
+#endif /* CONFIG_USB_OTG */
+
+/*------------- deprecated interface -----------------------------*/
 /* Context: can sleep */
 static inline int
 otg_start_hnp(struct usb_otg *otg)
@@ -113,6 +257,8 @@ otg_start_srp(struct usb_otg *otg)
 	return -ENOTSUPP;
 }
 
+/*---------------------------------------------------------------*/
+
 /* for OTG controller drivers (and maybe other stuff) */
 extern int usb_bus_start_enum(struct usb_bus *bus, unsigned port_num);
 
@@ -237,4 +383,6 @@ static inline int otg_start_gadget(struct usb_otg *otg, int on)
 	return otg->fsm.ops->start_gadget(otg, on);
 }
 
+int drd_statemachine(struct usb_otg *otg);
+
 #endif /* __LINUX_USB_OTG_H */
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH v8 09/14] usb: of: add an API to get OTG device from USB controller node
  2016-05-13 10:03 [PATCH v8 00/14] USB OTG/dual-role framework Roger Quadros
                   ` (7 preceding siblings ...)
  2016-05-13 10:03 ` [PATCH v8 08/14] usb: otg: add OTG/dual-role core Roger Quadros
@ 2016-05-13 10:03 ` Roger Quadros
  2016-05-20  9:29   ` [PATCH v9 " Roger Quadros
  2016-05-13 10:03 ` [PATCH v8 10/14] usb: otg: add hcd companion support Roger Quadros
                   ` (5 subsequent siblings)
  14 siblings, 1 reply; 62+ messages in thread
From: Roger Quadros @ 2016-05-13 10:03 UTC (permalink / raw)
  To: peter.chen
  Cc: balbi, tony, gregkh, dan.j.williams, mathias.nyman, Joao.Pinto,
	sergei.shtylyov, jun.li, grygorii.strashko, yoshihiro.shimoda.uh,
	robh, nsekhar, b-liu, linux-usb, linux-omap, linux-kernel,
	devicetree, Roger Quadros

The OTG controller and the USB controller can be linked via the
'otg-controller' property in the USB controller's device node.

of_usb_get_otg() can be used to get the OTG controller device
from the USB controller's device node.

Signed-off-by: Roger Quadros <rogerq@ti.com>
Acked-by: Peter Chen <peter.chen@nxp.com>
---
 Documentation/devicetree/bindings/usb/generic.txt |  3 +++
 drivers/usb/common/common.c                       | 27 +++++++++++++++++++++++
 include/linux/usb/of.h                            |  9 ++++++++
 3 files changed, 39 insertions(+)

diff --git a/Documentation/devicetree/bindings/usb/generic.txt b/Documentation/devicetree/bindings/usb/generic.txt
index bba8257..f6866c1 100644
--- a/Documentation/devicetree/bindings/usb/generic.txt
+++ b/Documentation/devicetree/bindings/usb/generic.txt
@@ -24,6 +24,9 @@ Optional properties:
 			optional for OTG device.
  - adp-disable: tells OTG controllers we want to disable OTG ADP, ADP is
 			optional for OTG device.
+ - otg-controller: phandle to otg controller. Host or gadget controllers can
+			contain this property to link it to a particular OTG
+			controller.
 
 This is an attribute to a USB controller such as:
 
diff --git a/drivers/usb/common/common.c b/drivers/usb/common/common.c
index e3d0161..d7ec471 100644
--- a/drivers/usb/common/common.c
+++ b/drivers/usb/common/common.c
@@ -238,6 +238,33 @@ int of_usb_update_otg_caps(struct device_node *np,
 }
 EXPORT_SYMBOL_GPL(of_usb_update_otg_caps);
 
+#ifdef CONFIG_USB_OTG
+/**
+ * of_usb_get_otg - get the OTG controller linked to the USB controller
+ * @np: Pointer to the device_node of the USB controller
+ * @otg_caps: Pointer to the target usb_otg_caps to be set
+ *
+ * Returns the OTG controller device or NULL on error.
+ */
+struct device *of_usb_get_otg(struct device_node *np)
+{
+	struct device_node *otg_np;
+	struct platform_device *pdev;
+
+	otg_np = of_parse_phandle(np, "otg-controller", 0);
+	if (!otg_np)
+		return NULL;
+
+	pdev = of_find_device_by_node(otg_np);
+	of_node_put(otg_np);
+	if (!pdev)
+		return NULL;
+
+	return &pdev->dev;
+}
+EXPORT_SYMBOL_GPL(of_usb_get_otg);
+#endif
+
 #endif
 
 MODULE_LICENSE("GPL");
diff --git a/include/linux/usb/of.h b/include/linux/usb/of.h
index de3237f..499a4e8 100644
--- a/include/linux/usb/of.h
+++ b/include/linux/usb/of.h
@@ -40,6 +40,15 @@ static inline struct device_node *usb_of_get_child_node
 }
 #endif
 
+#if IS_ENABLED(CONFIG_OF) && IS_ENABLED(CONFIG_USB_OTG)
+struct device *of_usb_get_otg(struct device_node *np);
+#else
+static inline struct device *of_usb_get_otg(struct device_node *np)
+{
+	return NULL;
+}
+#endif
+
 #if IS_ENABLED(CONFIG_OF) && IS_ENABLED(CONFIG_USB_SUPPORT)
 enum usb_phy_interface of_usb_get_phy_mode(struct device_node *np);
 #else
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH v8 10/14] usb: otg: add hcd companion support
  2016-05-13 10:03 [PATCH v8 00/14] USB OTG/dual-role framework Roger Quadros
                   ` (8 preceding siblings ...)
  2016-05-13 10:03 ` [PATCH v8 09/14] usb: of: add an API to get OTG device from USB controller node Roger Quadros
@ 2016-05-13 10:03 ` Roger Quadros
  2016-05-13 18:13   ` Rob Herring
  2016-05-20  9:32   ` [PATCH v9 " Roger Quadros
  2016-05-13 10:03 ` [PATCH v8 11/14] usb: otg: use dev_dbg() instead of VDBG() Roger Quadros
                   ` (4 subsequent siblings)
  14 siblings, 2 replies; 62+ messages in thread
From: Roger Quadros @ 2016-05-13 10:03 UTC (permalink / raw)
  To: peter.chen
  Cc: balbi, tony, gregkh, dan.j.williams, mathias.nyman, Joao.Pinto,
	sergei.shtylyov, jun.li, grygorii.strashko, yoshihiro.shimoda.uh,
	robh, nsekhar, b-liu, linux-usb, linux-omap, linux-kernel,
	devicetree, Roger Quadros

From: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>

Since some host controller (e.g. EHCI) needs a companion host controller
(e.g. OHCI), this patch adds such a configuration to use it in the OTG
core.

Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
Signed-off-by: Roger Quadros <rogerq@ti.com>
Acked-by: Peter Chen <peter.chen@nxp.com>
---
 Documentation/devicetree/bindings/usb/generic.txt |  3 +++
 drivers/usb/common/usb-otg.c                      | 32 ++++++++++++++++-------
 include/linux/usb/otg.h                           |  7 ++++-
 3 files changed, 32 insertions(+), 10 deletions(-)

diff --git a/Documentation/devicetree/bindings/usb/generic.txt b/Documentation/devicetree/bindings/usb/generic.txt
index f6866c1..1db1c33 100644
--- a/Documentation/devicetree/bindings/usb/generic.txt
+++ b/Documentation/devicetree/bindings/usb/generic.txt
@@ -27,6 +27,9 @@ Optional properties:
  - otg-controller: phandle to otg controller. Host or gadget controllers can
 			contain this property to link it to a particular OTG
 			controller.
+ - hcd-needs-companion: must be present if otg controller is dealing with
+			EHCI host controller that needs a companion OHCI host
+			controller.
 
 This is an attribute to a USB controller such as:
 
diff --git a/drivers/usb/common/usb-otg.c b/drivers/usb/common/usb-otg.c
index 64be6df..8a2a0d4 100644
--- a/drivers/usb/common/usb-otg.c
+++ b/drivers/usb/common/usb-otg.c
@@ -18,6 +18,7 @@
 #include <linux/list.h>
 #include <linux/of.h>
 #include <linux/of_platform.h>
+#include <linux/usb/of.h>
 #include <linux/usb/otg.h>
 #include <linux/usb/gadget.h>
 #include <linux/workqueue.h>
@@ -584,6 +585,10 @@ struct usb_otg *usb_otg_register(struct device *dev,
 	else
 		INIT_WORK(&otg->work, usb_drd_work);
 
+	if (of_find_property(dev->of_node, "hcd-needs-companion", NULL) ||
+	    config->hcd_needs_companion)	/* needs companion ? */
+		otg->flags |= OTG_FLAG_HCD_NEEDS_COMPANION;
+
 	otg->wq = create_freezable_workqueue("usb_otg");
 	if (!otg->wq) {
 		dev_err(dev, "otg: %s: can't create workqueue\n",
@@ -807,15 +812,18 @@ int usb_otg_register_hcd(struct usb_hcd *hcd, unsigned int irqnum,
 	/* HCD will be started by OTG fsm when needed */
 	mutex_lock(&otg->fsm.lock);
 	if (otg->primary_hcd.hcd) {
-		/* probably a shared HCD ? */
-		if (usb_otg_hcd_is_primary_hcd(hcd)) {
+		/* probably a shared HCD or a companion OHCI HCD ? */
+		if (!(otg->flags & OTG_FLAG_HCD_NEEDS_COMPANION) &&
+		    usb_otg_hcd_is_primary_hcd(hcd)) {
 			dev_err(otg_dev, "otg: primary host already registered\n");
 			goto err;
 		}
 
-		if (hcd->shared_hcd == otg->primary_hcd.hcd) {
+		if (otg->flags & OTG_FLAG_HCD_NEEDS_COMPANION ||
+		    (hcd->shared_hcd == otg->primary_hcd.hcd)) {
 			if (otg->shared_hcd.hcd) {
-				dev_err(otg_dev, "otg: shared host already registered\n");
+				dev_err(otg_dev,
+					"otg: shared/companion host already registered\n");
 				goto err;
 			}
 
@@ -823,10 +831,12 @@ int usb_otg_register_hcd(struct usb_hcd *hcd, unsigned int irqnum,
 			otg->shared_hcd.irqnum = irqnum;
 			otg->shared_hcd.irqflags = irqflags;
 			otg->shared_hcd.ops = ops;
-			dev_info(otg_dev, "otg: shared host %s registered\n",
+			dev_info(otg_dev,
+				 "otg: shared/companion host %s registered\n",
 				 dev_name(hcd->self.controller));
 		} else {
-			dev_err(otg_dev, "otg: invalid shared host %s\n",
+			dev_err(otg_dev,
+				"otg: invalid shared/companion host %s\n",
 				dev_name(hcd->self.controller));
 			goto err;
 		}
@@ -849,14 +859,17 @@ int usb_otg_register_hcd(struct usb_hcd *hcd, unsigned int irqnum,
 	 * we're ready only if we have shared HCD
 	 * or we don't need shared HCD.
 	 */
-	if (otg->shared_hcd.hcd || !otg->primary_hcd.hcd->shared_hcd) {
+	if (otg->shared_hcd.hcd ||
+	    (!(otg->flags & OTG_FLAG_HCD_NEEDS_COMPANION) &&
+	     !otg->primary_hcd.hcd->shared_hcd)) {
 		otg->host = hcd_to_bus(hcd);
 		/* FIXME: set bus->otg_port if this is true OTG port with HNP */
 
 		/* start FSM */
 		usb_otg_start_fsm(otg);
 	} else {
-		dev_dbg(otg_dev, "otg: can't start till shared host registers\n");
+		dev_dbg(otg_dev,
+			"otg: can't start till shared/companion host registers\n");
 	}
 
 	mutex_unlock(&otg->fsm.lock);
@@ -907,7 +920,8 @@ int usb_otg_unregister_hcd(struct usb_hcd *hcd)
 			 dev_name(hcd_dev));
 	} else if (hcd == otg->shared_hcd.hcd) {
 		otg->shared_hcd.hcd = NULL;
-		dev_info(otg_dev, "otg: shared host %s unregistered\n",
+		dev_info(otg_dev,
+			 "otg: shared/companion host %s unregistered\n",
 			 dev_name(hcd_dev));
 	} else {
 		dev_err(otg_dev, "otg: host %s wasn't registered with otg\n",
diff --git a/include/linux/usb/otg.h b/include/linux/usb/otg.h
index b094352..6f4ca77 100644
--- a/include/linux/usb/otg.h
+++ b/include/linux/usb/otg.h
@@ -57,7 +57,8 @@ struct otg_hcd {
  * @list: list of otg controllers
  * @work: otg state machine work
  * @wq: otg state machine work queue
- * @flags: to track if host/gadget is running
+ * @flags: to track if host/gadget is running, or to indicate if hcd needs
+ *	   companion
  */
 struct usb_otg {
 	u8			default_a;
@@ -84,6 +85,7 @@ struct usb_otg {
 	u32 flags;
 #define OTG_FLAG_GADGET_RUNNING (1 << 0)
 #define OTG_FLAG_HOST_RUNNING (1 << 1)
+#define OTG_FLAG_HCD_NEEDS_COMPANION (1 << 2)
 	/* use otg->fsm.lock for serializing access */
 
 /*------------- deprecated interface -----------------------------*/
@@ -125,11 +127,14 @@ struct usb_otg_caps {
  * @caps: otg capabilities of the controller
  * @ops: otg fsm operations
  * @otg_work: optional custom otg state machine work function
+ * @hcd_needs_companion: Indicates if host controller needs a companion
+ *			 controller
  */
 struct usb_otg_config {
 	struct usb_otg_caps *otg_caps;
 	struct otg_fsm_ops *fsm_ops;
 	void (*otg_work)(struct work_struct *work);
+	bool hcd_needs_companion;
 };
 
 extern const char *usb_otg_state_string(enum usb_otg_state state);
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH v8 11/14] usb: otg: use dev_dbg() instead of VDBG()
  2016-05-13 10:03 [PATCH v8 00/14] USB OTG/dual-role framework Roger Quadros
                   ` (9 preceding siblings ...)
  2016-05-13 10:03 ` [PATCH v8 10/14] usb: otg: add hcd companion support Roger Quadros
@ 2016-05-13 10:03 ` Roger Quadros
  2016-05-13 10:03 ` [PATCH v8 12/14] usb: hcd: Adapt to OTG core Roger Quadros
                   ` (3 subsequent siblings)
  14 siblings, 0 replies; 62+ messages in thread
From: Roger Quadros @ 2016-05-13 10:03 UTC (permalink / raw)
  To: peter.chen
  Cc: balbi, tony, gregkh, dan.j.williams, mathias.nyman, Joao.Pinto,
	sergei.shtylyov, jun.li, grygorii.strashko, yoshihiro.shimoda.uh,
	robh, nsekhar, b-liu, linux-usb, linux-omap, linux-kernel,
	devicetree, Roger Quadros

Now that we have a device reference in struct usb_otg
let's use dev_dbg() for debug messages.

Signed-off-by: Roger Quadros <rogerq@ti.com>
Acked-by: Peter Chen <peter.chen@nxp.com>
---
 drivers/usb/common/usb-otg-fsm.c | 19 +++++++------------
 1 file changed, 7 insertions(+), 12 deletions(-)

diff --git a/drivers/usb/common/usb-otg-fsm.c b/drivers/usb/common/usb-otg-fsm.c
index 2986b66..e6e58c2 100644
--- a/drivers/usb/common/usb-otg-fsm.c
+++ b/drivers/usb/common/usb-otg-fsm.c
@@ -30,13 +30,6 @@
 #include <linux/usb/otg.h>
 #include <linux/usb/otg-fsm.h>
 
-#ifdef VERBOSE
-#define VDBG(fmt, args...) pr_debug("[%s]  " fmt , \
-				 __func__, ## args)
-#else
-#define VDBG(stuff...)	do {} while (0)
-#endif
-
 /* Change USB protocol when there is a protocol change */
 static int otg_set_protocol(struct otg_fsm *fsm, int protocol)
 {
@@ -44,8 +37,9 @@ static int otg_set_protocol(struct otg_fsm *fsm, int protocol)
 	int ret = 0;
 
 	if (fsm->protocol != protocol) {
-		VDBG("Changing role fsm->protocol= %d; new protocol= %d\n",
-			fsm->protocol, protocol);
+		dev_vdbg(otg->dev,
+			 "Changing role fsm->protocol= %d; new protocol= %d\n",
+			 fsm->protocol, protocol);
 		/* stop old protocol */
 		if (fsm->protocol == PROTO_HOST)
 			ret = otg_start_host(otg, 0);
@@ -226,7 +220,7 @@ static int otg_set_state(struct otg_fsm *fsm, enum usb_otg_state new_state)
 
 	if (otg->state == new_state)
 		return 0;
-	VDBG("Set state: %s\n", usb_otg_state_string(new_state));
+	dev_vdbg(otg->dev, "Set state: %s\n", usb_otg_state_string(new_state));
 	otg_leave_state(fsm, otg->state);
 	switch (new_state) {
 	case OTG_STATE_B_IDLE:
@@ -358,7 +352,7 @@ int otg_statemachine(struct usb_otg *otg)
 
 	switch (state) {
 	case OTG_STATE_UNDEFINED:
-		VDBG("fsm->id = %d\n", fsm->id);
+		dev_vdbg(otg->dev, "fsm->id = %d\n", fsm->id);
 		if (fsm->id)
 			otg_set_state(fsm, OTG_STATE_B_IDLE);
 		else
@@ -466,7 +460,8 @@ int otg_statemachine(struct usb_otg *otg)
 	}
 	mutex_unlock(&fsm->lock);
 
-	VDBG("quit statemachine, changed = %d\n", fsm->state_changed);
+	dev_vdbg(otg->dev, "quit statemachine, changed = %d\n",
+		 fsm->state_changed);
 	return fsm->state_changed;
 }
 EXPORT_SYMBOL_GPL(otg_statemachine);
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH v8 12/14] usb: hcd: Adapt to OTG core
  2016-05-13 10:03 [PATCH v8 00/14] USB OTG/dual-role framework Roger Quadros
                   ` (10 preceding siblings ...)
  2016-05-13 10:03 ` [PATCH v8 11/14] usb: otg: use dev_dbg() instead of VDBG() Roger Quadros
@ 2016-05-13 10:03 ` Roger Quadros
  2016-05-13 10:03 ` [PATCH v8 13/14] usb: gadget: udc: adapt " Roger Quadros
                   ` (2 subsequent siblings)
  14 siblings, 0 replies; 62+ messages in thread
From: Roger Quadros @ 2016-05-13 10:03 UTC (permalink / raw)
  To: peter.chen
  Cc: balbi, tony, gregkh, dan.j.williams, mathias.nyman, Joao.Pinto,
	sergei.shtylyov, jun.li, grygorii.strashko, yoshihiro.shimoda.uh,
	robh, nsekhar, b-liu, linux-usb, linux-omap, linux-kernel,
	devicetree, Roger Quadros

Introduce usb_otg_add/remove_hcd() for use by host
controllers that are part of OTG/dual-role port.

Non Device tree platforms can use the otg_dev argument
to specify the OTG controller device. If otg_dev is NULL
then the device tree node's otg-controller property is used to
get the otg_dev device.

Signed-off-by: Roger Quadros <rogerq@ti.com>
Acked-by: Peter Chen <peter.chen@nxp.com>
---
 drivers/usb/core/hcd.c  | 55 +++++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/usb/hcd.h |  4 ++++
 2 files changed, 59 insertions(+)

diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index 9484539..cfc8232 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -46,6 +46,11 @@
 #include <linux/usb.h>
 #include <linux/usb/hcd.h>
 #include <linux/usb/phy.h>
+#include <linux/usb/otg.h>
+#include <linux/usb/of.h>
+
+#include <linux/of.h>
+#include <linux/of_platform.h>
 
 #include "usb.h"
 
@@ -3013,6 +3018,56 @@ void usb_remove_hcd(struct usb_hcd *hcd)
 }
 EXPORT_SYMBOL_GPL(usb_remove_hcd);
 
+static struct otg_hcd_ops otg_hcd_intf = {
+	.add = usb_add_hcd,
+	.remove = usb_remove_hcd,
+	.usb_bus_start_enum = usb_bus_start_enum,
+	.usb_control_msg = usb_control_msg,
+	.usb_hub_find_child = usb_hub_find_child,
+};
+
+/**
+ * usb_otg_add_hcd - Register the HCD with OTG core.
+ * @hcd: the usb_hcd structure to initialize
+ * @irqnum: Interrupt line to allocate
+ * @irqflags: Interrupt type flags
+ * @otg_dev: OTG controller device managing this HCD
+ *
+ * Registers the HCD with OTG core. OTG core will call usb_add_hcd()
+ * or usb_remove_hcd() as necessary.
+ * If otg_dev is NULL then device tree node is checked for OTG
+ * controller device via the otg-controller property.
+ */
+int usb_otg_add_hcd(struct usb_hcd *hcd,
+		    unsigned int irqnum, unsigned long irqflags,
+		    struct device *otg_dev)
+{
+	struct device *dev = hcd->self.controller;
+
+	if (!otg_dev) {
+		hcd->otg_dev = of_usb_get_otg(dev->of_node);
+		if (!hcd->otg_dev)
+			return -ENODEV;
+	} else {
+		hcd->otg_dev = otg_dev;
+	}
+
+	return usb_otg_register_hcd(hcd, irqnum, irqflags, &otg_hcd_intf);
+}
+EXPORT_SYMBOL_GPL(usb_otg_add_hcd);
+
+/**
+ * usb_otg_remove_hcd - Unregister the HCD with OTG core.
+ * @hcd: the usb_hcd structure to remove
+ *
+ * Unregisters the HCD from the OTG core.
+ */
+void usb_otg_remove_hcd(struct usb_hcd *hcd)
+{
+	usb_otg_unregister_hcd(hcd);
+}
+EXPORT_SYMBOL_GPL(usb_otg_remove_hcd);
+
 void
 usb_hcd_platform_shutdown(struct platform_device *dev)
 {
diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h
index 2017cd4..adcf2e7 100644
--- a/include/linux/usb/hcd.h
+++ b/include/linux/usb/hcd.h
@@ -472,6 +472,10 @@ extern int usb_hcd_is_primary_hcd(struct usb_hcd *hcd);
 extern int usb_add_hcd(struct usb_hcd *hcd,
 		unsigned int irqnum, unsigned long irqflags);
 extern void usb_remove_hcd(struct usb_hcd *hcd);
+extern int usb_otg_add_hcd(struct usb_hcd *hcd,
+			   unsigned int irqnum, unsigned long irqflags,
+			   struct device *otg_dev);
+extern void usb_otg_remove_hcd(struct usb_hcd *hcd);
 extern int usb_hcd_find_raw_port_number(struct usb_hcd *hcd, int port1);
 
 struct platform_device;
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH v8 13/14] usb: gadget: udc: adapt to OTG core
  2016-05-13 10:03 [PATCH v8 00/14] USB OTG/dual-role framework Roger Quadros
                   ` (11 preceding siblings ...)
  2016-05-13 10:03 ` [PATCH v8 12/14] usb: hcd: Adapt to OTG core Roger Quadros
@ 2016-05-13 10:03 ` Roger Quadros
  2016-05-16  7:02   ` Peter Chen
  2016-06-01  7:38   ` Peter Chen
  2016-05-13 10:03 ` [PATCH v8 14/14] usb: host: xhci-plat: Add otg device to platform data Roger Quadros
  2016-05-30  9:29 ` [PATCH v8 00/14] USB OTG/dual-role framework Peter Chen
  14 siblings, 2 replies; 62+ messages in thread
From: Roger Quadros @ 2016-05-13 10:03 UTC (permalink / raw)
  To: peter.chen
  Cc: balbi, tony, gregkh, dan.j.williams, mathias.nyman, Joao.Pinto,
	sergei.shtylyov, jun.li, grygorii.strashko, yoshihiro.shimoda.uh,
	robh, nsekhar, b-liu, linux-usb, linux-omap, linux-kernel,
	devicetree, Roger Quadros

The OTG state machine needs a mechanism to start and
stop the gadget controller as well as connect/disconnect
from the bus. Add usb_gadget_start(), usb_gadget_stop()
and usb_gadget_connect_control().

Introduce usb_otg_add_gadget_udc() to allow controller drivers
to register a gadget controller that is part of an OTG instance.

Register with OTG core when gadget function driver
is available and unregister when function driver is unbound.

We need to unlock the usb_lock mutex before calling
usb_otg_register_gadget() in udc_bind_to_driver() and
usb_gadget_remove_driver() else it will cause a circular
locking dependency.

Ignore softconnect sysfs control when we're in OTG
mode as OTG FSM takes care of gadget softconnect using
the b_bus_req mechanism.

Signed-off-by: Roger Quadros <rogerq@ti.com>
---
 drivers/usb/gadget/udc/udc-core.c | 194 ++++++++++++++++++++++++++++++++++++--
 include/linux/usb/gadget.h        |   4 +
 2 files changed, 189 insertions(+), 9 deletions(-)

diff --git a/drivers/usb/gadget/udc/udc-core.c b/drivers/usb/gadget/udc/udc-core.c
index 4151597..21c85ef 100644
--- a/drivers/usb/gadget/udc/udc-core.c
+++ b/drivers/usb/gadget/udc/udc-core.c
@@ -28,6 +28,11 @@
 #include <linux/usb/ch9.h>
 #include <linux/usb/gadget.h>
 #include <linux/usb.h>
+#include <linux/usb/otg.h>
+#include <linux/usb/of.h>
+
+#include <linux/of.h>
+#include <linux/of_platform.h>
 
 /**
  * struct usb_udc - describes one usb device controller
@@ -325,6 +330,119 @@ static inline void usb_gadget_udc_stop(struct usb_udc *udc)
 }
 
 /**
+ * usb_gadget_to_udc - get the UDC owning the gadget
+ *
+ * udc_lock must be held.
+ * Returs NULL if UDC is not found.
+ */
+static struct usb_udc *usb_gadget_to_udc(struct usb_gadget *gadget)
+{
+	struct usb_udc *udc;
+
+	list_for_each_entry(udc, &udc_list, list)
+		if (udc->gadget == gadget)
+			return udc;
+
+	return NULL;
+}
+
+/**
+ * usb_gadget_start - start the usb gadget controller
+ * @gadget: the gadget device to start
+ *
+ * This is external API for use by OTG core.
+ *
+ * Start the usb device controller. Does not connect to the bus.
+ */
+static int usb_gadget_start(struct usb_gadget *gadget)
+{
+	int ret;
+	struct usb_udc *udc;
+
+	mutex_lock(&udc_lock);
+	udc = usb_gadget_to_udc(gadget);
+	if (!udc) {
+		dev_err(gadget->dev.parent, "%s: gadget not registered.\n",
+			__func__);
+		mutex_unlock(&udc_lock);
+		return -EINVAL;
+	}
+
+	ret = usb_gadget_udc_start(udc);
+	if (ret)
+		dev_err(&udc->dev, "USB Device Controller didn't start: %d\n",
+			ret);
+
+	mutex_unlock(&udc_lock);
+
+	return ret;
+}
+
+/**
+ * usb_gadget_stop - stop the usb gadget controller
+ * @gadget: the gadget device we want to stop
+ *
+ * This is external API for use by OTG core.
+ *
+ * Stop the gadget controller. Does not disconnect from the bus.
+ * Caller must ensure that gadget has disconnected from the bus
+ * before calling usb_gadget_stop().
+ */
+static int usb_gadget_stop(struct usb_gadget *gadget)
+{
+	struct usb_udc *udc;
+
+	mutex_lock(&udc_lock);
+	udc = usb_gadget_to_udc(gadget);
+	if (!udc) {
+		dev_err(gadget->dev.parent, "%s: gadget not registered.\n",
+			__func__);
+		mutex_unlock(&udc_lock);
+		return -EINVAL;
+	}
+
+	if (gadget->connected) {
+		dev_err(gadget->dev.parent,
+			"%s: called while still connected\n", __func__);
+		mutex_unlock(&udc_lock);
+		return -EINVAL;
+	}
+
+	usb_gadget_udc_stop(udc);
+	mutex_unlock(&udc_lock);
+
+	return 0;
+}
+
+static int usb_gadget_connect_control(struct usb_gadget *gadget, bool connect)
+{
+	struct usb_udc *udc;
+
+	mutex_lock(&udc_lock);
+	udc = usb_gadget_to_udc(gadget);
+	if (!udc) {
+		dev_err(gadget->dev.parent, "%s: gadget not registered.\n",
+			__func__);
+		mutex_unlock(&udc_lock);
+		return -EINVAL;
+	}
+
+	if (connect) {
+		if (!gadget->connected)
+			usb_gadget_connect(udc->gadget);
+	} else {
+		if (gadget->connected) {
+			usb_gadget_disconnect(udc->gadget);
+			udc->driver->disconnect(udc->gadget);
+		}
+	}
+
+	mutex_unlock(&udc_lock);
+
+	return 0;
+}
+
+/**
  * usb_udc_release - release the usb_udc struct
  * @dev: the dev member within usb_udc
  *
@@ -486,6 +604,33 @@ int usb_add_gadget_udc(struct device *parent, struct usb_gadget *gadget)
 }
 EXPORT_SYMBOL_GPL(usb_add_gadget_udc);
 
+/**
+ * usb_otg_add_gadget_udc - adds a new gadget to the udc class driver list
+ * @parent: the parent device to this udc. Usually the controller
+ * driver's device.
+ * @gadget: the gadget to be added to the list
+ * @otg_dev: the OTG controller device
+ *
+ * If otg_dev is NULL then device tree node is checked
+ * for OTG controller via the otg-controller property.
+ * Returns zero on success, negative errno otherwise.
+ */
+int usb_otg_add_gadget_udc(struct device *parent, struct usb_gadget *gadget,
+			   struct device *otg_dev)
+{
+	if (!otg_dev) {
+		gadget->otg_dev = of_usb_get_otg(parent->of_node);
+		if (!gadget->otg_dev)
+			return -ENODEV;
+	} else {
+		gadget->otg_dev = otg_dev;
+	}
+
+	return usb_add_gadget_udc_release(parent, gadget, NULL);
+}
+EXPORT_SYMBOL_GPL(usb_otg_add_gadget_udc);
+
+/* udc_lock must be held */
 static void usb_gadget_remove_driver(struct usb_udc *udc)
 {
 	dev_dbg(&udc->dev, "unregistering UDC driver [%s]\n",
@@ -493,10 +638,18 @@ static void usb_gadget_remove_driver(struct usb_udc *udc)
 
 	kobject_uevent(&udc->dev.kobj, KOBJ_CHANGE);
 
-	usb_gadget_disconnect(udc->gadget);
-	udc->driver->disconnect(udc->gadget);
+	/* If OTG, the otg core ensures UDC is stopped on unregister */
+	if (udc->gadget->otg_dev) {
+		mutex_unlock(&udc_lock);
+		usb_otg_unregister_gadget(udc->gadget);
+		mutex_lock(&udc_lock);
+	} else {
+		usb_gadget_disconnect(udc->gadget);
+		udc->driver->disconnect(udc->gadget);
+		usb_gadget_udc_stop(udc);
+	}
+
 	udc->driver->unbind(udc->gadget);
-	usb_gadget_udc_stop(udc);
 
 	udc->driver = NULL;
 	udc->dev.driver = NULL;
@@ -530,6 +683,8 @@ void usb_del_gadget_udc(struct usb_gadget *gadget)
 	}
 	mutex_unlock(&udc_lock);
 
+	mutex_unlock(&udc_lock);
+
 	kobject_uevent(&udc->dev.kobj, KOBJ_REMOVE);
 	flush_work(&gadget->work);
 	device_unregister(&udc->dev);
@@ -539,6 +694,13 @@ EXPORT_SYMBOL_GPL(usb_del_gadget_udc);
 
 /* ------------------------------------------------------------------------- */
 
+struct otg_gadget_ops otg_gadget_intf = {
+	.start = usb_gadget_start,
+	.stop = usb_gadget_stop,
+	.connect_control = usb_gadget_connect_control,
+};
+
+/* udc_lock must be held */
 static int udc_bind_to_driver(struct usb_udc *udc, struct usb_gadget_driver *driver)
 {
 	int ret;
@@ -553,12 +715,20 @@ static int udc_bind_to_driver(struct usb_udc *udc, struct usb_gadget_driver *dri
 	ret = driver->bind(udc->gadget, driver);
 	if (ret)
 		goto err1;
-	ret = usb_gadget_udc_start(udc);
-	if (ret) {
-		driver->unbind(udc->gadget);
-		goto err1;
+
+	/* If OTG, the otg core starts the UDC when needed */
+	if (udc->gadget->otg_dev) {
+		mutex_unlock(&udc_lock);
+		usb_otg_register_gadget(udc->gadget, &otg_gadget_intf);
+		mutex_lock(&udc_lock);
+	} else {
+		ret = usb_gadget_udc_start(udc);
+		if (ret) {
+			driver->unbind(udc->gadget);
+			goto err1;
+		}
+		usb_udc_connect_control(udc);
 	}
-	usb_udc_connect_control(udc);
 
 	kobject_uevent(&udc->dev.kobj, KOBJ_CHANGE);
 	return 0;
@@ -660,9 +830,15 @@ static ssize_t usb_udc_softconn_store(struct device *dev,
 		return -EOPNOTSUPP;
 	}
 
+	/* In OTG mode we don't support softconnect, but b_bus_req */
+	if (udc->gadget->otg_dev) {
+		dev_err(dev, "soft-connect not supported in OTG mode\n");
+		return -EOPNOTSUPP;
+	}
+
 	if (sysfs_streq(buf, "connect")) {
 		usb_gadget_udc_start(udc);
-		usb_gadget_connect(udc->gadget);
+		usb_udc_connect_control(udc);
 	} else if (sysfs_streq(buf, "disconnect")) {
 		usb_gadget_disconnect(udc->gadget);
 		udc->driver->disconnect(udc->gadget);
diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h
index 3ecfddd..79d654f 100644
--- a/include/linux/usb/gadget.h
+++ b/include/linux/usb/gadget.h
@@ -1162,6 +1162,10 @@ extern int usb_add_gadget_udc(struct device *parent, struct usb_gadget *gadget);
 extern void usb_del_gadget_udc(struct usb_gadget *gadget);
 extern char *usb_get_gadget_udc_name(void);
 
+extern int usb_otg_add_gadget_udc(struct device *parent,
+				  struct usb_gadget *gadget,
+				  struct device *otg_dev);
+
 /*-------------------------------------------------------------------------*/
 
 /* utility to simplify dealing with string descriptors */
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH v8 14/14] usb: host: xhci-plat: Add otg device to platform data
  2016-05-13 10:03 [PATCH v8 00/14] USB OTG/dual-role framework Roger Quadros
                   ` (12 preceding siblings ...)
  2016-05-13 10:03 ` [PATCH v8 13/14] usb: gadget: udc: adapt " Roger Quadros
@ 2016-05-13 10:03 ` Roger Quadros
  2016-05-30  9:29 ` [PATCH v8 00/14] USB OTG/dual-role framework Peter Chen
  14 siblings, 0 replies; 62+ messages in thread
From: Roger Quadros @ 2016-05-13 10:03 UTC (permalink / raw)
  To: peter.chen
  Cc: balbi, tony, gregkh, dan.j.williams, mathias.nyman, Joao.Pinto,
	sergei.shtylyov, jun.li, grygorii.strashko, yoshihiro.shimoda.uh,
	robh, nsekhar, b-liu, linux-usb, linux-omap, linux-kernel,
	devicetree, Roger Quadros

Host controllers that are part of an OTG/dual-role instance
need to somehow pass the OTG controller device information
to the HCD core.

We use platform data to pass the OTG controller device.

Signed-off-by: Roger Quadros <rogerq@ti.com>
Reviewed-by: Peter Chen <peter.chen@nxp.com>
---
 drivers/usb/host/xhci-plat.c     | 35 ++++++++++++++++++++++++++++-------
 include/linux/usb/xhci_pdriver.h |  3 +++
 2 files changed, 31 insertions(+), 7 deletions(-)

diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c
index 5c15e9b..84ebe18 100644
--- a/drivers/usb/host/xhci-plat.c
+++ b/drivers/usb/host/xhci-plat.c
@@ -230,11 +230,20 @@ static int xhci_plat_probe(struct platform_device *pdev)
 			goto put_usb3_hcd;
 	}
 
-	ret = usb_add_hcd(hcd, irq, IRQF_SHARED);
+	if (pdata && pdata->otg_dev)
+		ret = usb_otg_add_hcd(hcd, irq, IRQF_SHARED, pdata->otg_dev);
+	else
+		ret = usb_add_hcd(hcd, irq, IRQF_SHARED);
+
 	if (ret)
 		goto disable_usb_phy;
 
-	ret = usb_add_hcd(xhci->shared_hcd, irq, IRQF_SHARED);
+	if (pdata && pdata->otg_dev)
+		ret = usb_otg_add_hcd(xhci->shared_hcd, irq, IRQF_SHARED,
+				      pdata->otg_dev);
+	else
+		ret = usb_add_hcd(xhci->shared_hcd, irq, IRQF_SHARED);
+
 	if (ret)
 		goto dealloc_usb2_hcd;
 
@@ -242,7 +251,10 @@ static int xhci_plat_probe(struct platform_device *pdev)
 
 
 dealloc_usb2_hcd:
-	usb_remove_hcd(hcd);
+	if (pdata && pdata->otg_dev)
+		usb_otg_remove_hcd(hcd);
+	else
+		usb_remove_hcd(hcd);
 
 disable_usb_phy:
 	usb_phy_shutdown(hcd->usb_phy);
@@ -260,16 +272,25 @@ put_hcd:
 	return ret;
 }
 
-static int xhci_plat_remove(struct platform_device *dev)
+static int xhci_plat_remove(struct platform_device *pdev)
 {
-	struct usb_hcd	*hcd = platform_get_drvdata(dev);
+	struct usb_hcd	*hcd = platform_get_drvdata(pdev);
 	struct xhci_hcd	*xhci = hcd_to_xhci(hcd);
 	struct clk *clk = xhci->clk;
+	struct usb_xhci_pdata *pdata = dev_get_platdata(&pdev->dev);
+
+	if (pdata && pdata->otg_dev)
+		usb_otg_remove_hcd(xhci->shared_hcd);
+	else
+		usb_remove_hcd(xhci->shared_hcd);
 
-	usb_remove_hcd(xhci->shared_hcd);
 	usb_phy_shutdown(hcd->usb_phy);
 
-	usb_remove_hcd(hcd);
+	if (pdata && pdata->otg_dev)
+		usb_otg_remove_hcd(hcd);
+	else
+		usb_remove_hcd(hcd);
+
 	usb_put_hcd(xhci->shared_hcd);
 
 	if (!IS_ERR(clk))
diff --git a/include/linux/usb/xhci_pdriver.h b/include/linux/usb/xhci_pdriver.h
index 376654b..5c68b83 100644
--- a/include/linux/usb/xhci_pdriver.h
+++ b/include/linux/usb/xhci_pdriver.h
@@ -18,10 +18,13 @@
  *
  * @usb3_lpm_capable:	determines if this xhci platform supports USB3
  *			LPM capability
+ * @otg_dev:		OTG controller device. Only requied if part of
+ *			OTG/dual-role.
  *
  */
 struct usb_xhci_pdata {
 	unsigned	usb3_lpm_capable:1;
+	struct device	*otg_dev;
 };
 
 #endif /* __USB_CORE_XHCI_PDRIVER_H */
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* Re: [PATCH v8 10/14] usb: otg: add hcd companion support
  2016-05-13 10:03 ` [PATCH v8 10/14] usb: otg: add hcd companion support Roger Quadros
@ 2016-05-13 18:13   ` Rob Herring
  2016-05-16  8:12     ` Roger Quadros
  2016-05-20  9:32   ` [PATCH v9 " Roger Quadros
  1 sibling, 1 reply; 62+ messages in thread
From: Rob Herring @ 2016-05-13 18:13 UTC (permalink / raw)
  To: Roger Quadros
  Cc: Peter Chen, balbi, Tony Lindgren, Greg Kroah-Hartman,
	Dan Williams, Mathias Nyman, Joao Pinto, Sergei Shtylyov, Li Jun,
	Grygorii Strashko, Shimoda, Yoshihiro, Sekhar Nori, Bin Liu,
	Linux USB List, linux-omap, linux-kernel, devicetree

On Fri, May 13, 2016 at 5:03 AM, Roger Quadros <rogerq@ti.com> wrote:
> From: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
>
> Since some host controller (e.g. EHCI) needs a companion host controller
> (e.g. OHCI), this patch adds such a configuration to use it in the OTG
> core.
>
> Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
> Signed-off-by: Roger Quadros <rogerq@ti.com>
> Acked-by: Peter Chen <peter.chen@nxp.com>
> ---
>  Documentation/devicetree/bindings/usb/generic.txt |  3 +++
>  drivers/usb/common/usb-otg.c                      | 32 ++++++++++++++++-------
>  include/linux/usb/otg.h                           |  7 ++++-
>  3 files changed, 32 insertions(+), 10 deletions(-)
>
> diff --git a/Documentation/devicetree/bindings/usb/generic.txt b/Documentation/devicetree/bindings/usb/generic.txt
> index f6866c1..1db1c33 100644
> --- a/Documentation/devicetree/bindings/usb/generic.txt
> +++ b/Documentation/devicetree/bindings/usb/generic.txt
> @@ -27,6 +27,9 @@ Optional properties:
>   - otg-controller: phandle to otg controller. Host or gadget controllers can
>                         contain this property to link it to a particular OTG
>                         controller.
> + - hcd-needs-companion: must be present if otg controller is dealing with
> +                       EHCI host controller that needs a companion OHCI host
> +                       controller.

I thought the conclusion was this is not needed?

One thing that is not clear here is otg-controller is a host or device
property while hcd-needs-companion is an OTG controller property.
These lists should be separated.

Rob

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v8 13/14] usb: gadget: udc: adapt to OTG core
  2016-05-13 10:03 ` [PATCH v8 13/14] usb: gadget: udc: adapt " Roger Quadros
@ 2016-05-16  7:02   ` Peter Chen
  2016-05-16  8:26     ` Roger Quadros
  2016-06-01  7:38   ` Peter Chen
  1 sibling, 1 reply; 62+ messages in thread
From: Peter Chen @ 2016-05-16  7:02 UTC (permalink / raw)
  To: Roger Quadros
  Cc: peter.chen, balbi, tony, gregkh, dan.j.williams, mathias.nyman,
	Joao.Pinto, sergei.shtylyov, jun.li, grygorii.strashko,
	yoshihiro.shimoda.uh, robh, nsekhar, b-liu, linux-usb,
	linux-omap, linux-kernel, devicetree

On Fri, May 13, 2016 at 01:03:27PM +0300, Roger Quadros wrote:
> +
> +static int usb_gadget_connect_control(struct usb_gadget *gadget, bool connect)
> +{
> +	struct usb_udc *udc;
> +
> +	mutex_lock(&udc_lock);
> +	udc = usb_gadget_to_udc(gadget);
> +	if (!udc) {
> +		dev_err(gadget->dev.parent, "%s: gadget not registered.\n",
> +			__func__);
> +		mutex_unlock(&udc_lock);
> +		return -EINVAL;
> +	}
> +
> +	if (connect) {
> +		if (!gadget->connected)
> +			usb_gadget_connect(udc->gadget);
> +	} else {
> +		if (gadget->connected) {
> +			usb_gadget_disconnect(udc->gadget);
> +			udc->driver->disconnect(udc->gadget);
> +		}
> +	}
> +
> +	mutex_unlock(&udc_lock);
> +
> +	return 0;
> +}
> +

Since this is called for vbus interrupt, why not using
usb_udc_vbus_handler directly, and call udc->driver->disconnect
at usb_gadget_stop.

>  	return 0;
> @@ -660,9 +830,15 @@ static ssize_t usb_udc_softconn_store(struct device *dev,
>  		return -EOPNOTSUPP;
>  	}
>  
> +	/* In OTG mode we don't support softconnect, but b_bus_req */
> +	if (udc->gadget->otg_dev) {
> +		dev_err(dev, "soft-connect not supported in OTG mode\n");
> +		return -EOPNOTSUPP;
> +	}
> +

The soft-connect can be supported at dual-role mode currently, we can
use b_bus_req entry once it is implemented later.

>  	if (sysfs_streq(buf, "connect")) {
>  		usb_gadget_udc_start(udc);
> -		usb_gadget_connect(udc->gadget);
> +		usb_udc_connect_control(udc);

This line seems to be not related with this patch.

-- 

Best Regards,
Peter Chen

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v8 10/14] usb: otg: add hcd companion support
  2016-05-13 18:13   ` Rob Herring
@ 2016-05-16  8:12     ` Roger Quadros
  0 siblings, 0 replies; 62+ messages in thread
From: Roger Quadros @ 2016-05-16  8:12 UTC (permalink / raw)
  To: Rob Herring
  Cc: Peter Chen, balbi, Tony Lindgren, Greg Kroah-Hartman,
	Dan Williams, Mathias Nyman, Joao Pinto, Sergei Shtylyov, Li Jun,
	Grygorii Strashko, Shimoda, Yoshihiro, Sekhar Nori, Bin Liu,
	Linux USB List, linux-omap, linux-kernel, devicetree

On 13/05/16 21:13, Rob Herring wrote:
> On Fri, May 13, 2016 at 5:03 AM, Roger Quadros <rogerq@ti.com> wrote:
>> From: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
>>
>> Since some host controller (e.g. EHCI) needs a companion host controller
>> (e.g. OHCI), this patch adds such a configuration to use it in the OTG
>> core.
>>
>> Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
>> Signed-off-by: Roger Quadros <rogerq@ti.com>
>> Acked-by: Peter Chen <peter.chen@nxp.com>
>> ---
>>  Documentation/devicetree/bindings/usb/generic.txt |  3 +++
>>  drivers/usb/common/usb-otg.c                      | 32 ++++++++++++++++-------
>>  include/linux/usb/otg.h                           |  7 ++++-
>>  3 files changed, 32 insertions(+), 10 deletions(-)
>>
>> diff --git a/Documentation/devicetree/bindings/usb/generic.txt b/Documentation/devicetree/bindings/usb/generic.txt
>> index f6866c1..1db1c33 100644
>> --- a/Documentation/devicetree/bindings/usb/generic.txt
>> +++ b/Documentation/devicetree/bindings/usb/generic.txt
>> @@ -27,6 +27,9 @@ Optional properties:
>>   - otg-controller: phandle to otg controller. Host or gadget controllers can
>>                         contain this property to link it to a particular OTG
>>                         controller.
>> + - hcd-needs-companion: must be present if otg controller is dealing with
>> +                       EHCI host controller that needs a companion OHCI host
>> +                       controller.
> 
> I thought the conclusion was this is not needed?

This is still needed to differentiate between primary+shared HCD case vs
primary + primary-companion HCD case.

> 
> One thing that is not clear here is otg-controller is a host or device
> property while hcd-needs-companion is an OTG controller property.
> These lists should be separated.

Agreed. I'll fix that up.

cheers,
-roger

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v8 13/14] usb: gadget: udc: adapt to OTG core
  2016-05-16  7:02   ` Peter Chen
@ 2016-05-16  8:26     ` Roger Quadros
  2016-05-16  9:23       ` Peter Chen
  0 siblings, 1 reply; 62+ messages in thread
From: Roger Quadros @ 2016-05-16  8:26 UTC (permalink / raw)
  To: Peter Chen
  Cc: peter.chen, balbi, tony, gregkh, dan.j.williams, mathias.nyman,
	Joao.Pinto, sergei.shtylyov, jun.li, grygorii.strashko,
	yoshihiro.shimoda.uh, robh, nsekhar, b-liu, linux-usb,
	linux-omap, linux-kernel, devicetree

Hi,

On 16/05/16 10:02, Peter Chen wrote:
> On Fri, May 13, 2016 at 01:03:27PM +0300, Roger Quadros wrote:
>> +
>> +static int usb_gadget_connect_control(struct usb_gadget *gadget, bool connect)
>> +{
>> +	struct usb_udc *udc;
>> +
>> +	mutex_lock(&udc_lock);
>> +	udc = usb_gadget_to_udc(gadget);
>> +	if (!udc) {
>> +		dev_err(gadget->dev.parent, "%s: gadget not registered.\n",
>> +			__func__);
>> +		mutex_unlock(&udc_lock);
>> +		return -EINVAL;
>> +	}
>> +
>> +	if (connect) {
>> +		if (!gadget->connected)
>> +			usb_gadget_connect(udc->gadget);
>> +	} else {
>> +		if (gadget->connected) {
>> +			usb_gadget_disconnect(udc->gadget);
>> +			udc->driver->disconnect(udc->gadget);
>> +		}
>> +	}
>> +
>> +	mutex_unlock(&udc_lock);
>> +
>> +	return 0;
>> +}
>> +
> 
> Since this is called for vbus interrupt, why not using
> usb_udc_vbus_handler directly, and call udc->driver->disconnect
> at usb_gadget_stop.

We can't assume that this is always called for vbus interrupt so
I decided not to call usb_udc_vbus_handler.

udc->vbus is really pointless for us. We keep vbus states in our
state machine and leave udc->vbus as ture always.

Why do you want to move udc->driver->disconnect() to stop?
If USB controller disconnected from bus then the gadget driver
must be notified about the disconnect immediately. The controller
may or may not be stopped by the core.

> 
>>  	return 0;
>> @@ -660,9 +830,15 @@ static ssize_t usb_udc_softconn_store(struct device *dev,
>>  		return -EOPNOTSUPP;
>>  	}
>>  
>> +	/* In OTG mode we don't support softconnect, but b_bus_req */
>> +	if (udc->gadget->otg_dev) {
>> +		dev_err(dev, "soft-connect not supported in OTG mode\n");
>> +		return -EOPNOTSUPP;
>> +	}
>> +
> 
> The soft-connect can be supported at dual-role mode currently, we can
> use b_bus_req entry once it is implemented later.

Soft-connect should be done via sysfs handling within the OTG core.
This can be added later. I don't want anything outside the OTG core
to handle soft-connect behaviour as it will be hard to keep things
in sync.

I can update the comment to something like this.

/* In OTG/dual-role mode, soft-connect should be handled by OTG core */

> 
>>  	if (sysfs_streq(buf, "connect")) {
>>  		usb_gadget_udc_start(udc);
>> -		usb_gadget_connect(udc->gadget);
>> +		usb_udc_connect_control(udc);
> 
> This line seems to be not related with this patch.
> 
Right. I'll remove it.

cheers,
-roger

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v8 08/14] usb: otg: add OTG/dual-role core
  2016-05-13 10:03 ` [PATCH v8 08/14] usb: otg: add OTG/dual-role core Roger Quadros
@ 2016-05-16  9:00   ` Roger Quadros
       [not found]     ` <CAL411-qb0dHQrn+AarSApCq6L=toKPRerLKDcx_H+5WDWu_VDg@mail.gmail.com>
  2016-05-24  9:45   ` Roger Quadros
  1 sibling, 1 reply; 62+ messages in thread
From: Roger Quadros @ 2016-05-16  9:00 UTC (permalink / raw)
  To: peter.chen
  Cc: balbi, tony, gregkh, dan.j.williams, mathias.nyman, Joao.Pinto,
	sergei.shtylyov, jun.li, grygorii.strashko, yoshihiro.shimoda.uh,
	robh, nsekhar, b-liu, linux-usb, linux-omap, linux-kernel,
	devicetree

On 13/05/16 13:03, Roger Quadros wrote:
> It provides APIs for the following tasks
> 
> - Registering an OTG/dual-role capable controller
> - Registering Host and Gadget controllers to OTG core
> - Providing inputs to and kicking the OTG state machine
> 
> Provide a dual-role device (DRD) state machine.
> DRD mode is a reduced functionality OTG mode. In this mode
> we don't support SRP, HNP and dynamic role-swap.
> 
> In DRD operation, the controller mode (Host or Peripheral)
> is decided based on the ID pin status. Once a cable plug (Type-A
> or Type-B) is attached the controller selects the state
> and doesn't change till the cable in unplugged and a different
> cable type is inserted.
> 
> As we don't need most of the complex OTG states and OTG timers
> we implement a lean DRD state machine in usb-otg.c.
> The DRD state machine is only interested in 2 hardware inputs
> 'id' and 'b_sess_vld'.
> 
> Signed-off-by: Roger Quadros <rogerq@ti.com>
> ---
>  drivers/usb/common/Makefile  |    2 +-
>  drivers/usb/common/usb-otg.c | 1042 ++++++++++++++++++++++++++++++++++++++++++
>  drivers/usb/core/Kconfig     |    4 +-
>  include/linux/usb/gadget.h   |    2 +
>  include/linux/usb/hcd.h      |    1 +
>  include/linux/usb/otg-fsm.h  |    7 +
>  include/linux/usb/otg.h      |  154 ++++++-
>  7 files changed, 1206 insertions(+), 6 deletions(-)
>  create mode 100644 drivers/usb/common/usb-otg.c


This patch causes the following build issues when CONFIG_USB_GADGET=m, CONFIG_USB=m,
CONFIG_USB_COMMON=m and CONFIG_USB_OTG=y

ERROR: "usb_otg_register_gadget" [drivers/usb/gadget/udc/udc-core.ko] undefined!
ERROR: "usb_otg_unregister_gadget" [drivers/usb/gadget/udc/udc-core.ko] undefined!
ERROR: "usb_otg_register_hcd" [drivers/usb/core/usbcore.ko] undefined!
ERROR: "usb_otg_unregister_hcd" [drivers/usb/core/usbcore.ko] undefined!
ERROR: "otg_statemachine" [drivers/usb/chipidea/ci_hdrc.ko] undefined!
scripts/Makefile.modpost:91: recipe for target '__modpost' failed
make[1]: *** [__modpost] Error 1
Makefile:1141: recipe for target 'modules' failed
make: *** [modules] Error 2
make: *** Waiting for unfinished jobs....

drivers/built-in.o: In function `drd_set_state':
usb-otg.c:(.text+0x2b4242): undefined reference to `usb_otg_state_string'
drivers/built-in.o: In function `drd_statemachine':
(.text+0x2b4b4c): undefined reference to `usb_otg_state_string'
Makefile:937: recipe for target 'vmlinux' failed

I'll fix it up with the following diff.

diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile
index dca7856..16a5b55 100644
--- a/drivers/usb/Makefile
+++ b/drivers/usb/Makefile
@@ -59,5 +59,6 @@ obj-$(CONFIG_USB_RENESAS_USBHS)	+= renesas_usbhs/
 obj-$(CONFIG_USB_GADGET)	+= gadget/
 
 obj-$(CONFIG_USB_COMMON)	+= common/
+obj-$(CONFIG_USB_OTG)		+= common/
 
 obj-$(CONFIG_USBIP_CORE)	+= usbip/
diff --git a/drivers/usb/common/usb-otg.c b/drivers/usb/common/usb-otg.c
index 77048aa..17e449e 100644
--- a/drivers/usb/common/usb-otg.c
+++ b/drivers/usb/common/usb-otg.c
@@ -56,6 +56,30 @@ static int usb_otg_hcd_is_primary_hcd(struct usb_hcd *hcd)
 	return hcd == hcd->primary_hcd;
 }
 
+static const char *otg_state_string(enum usb_otg_state state)
+{
+	static const char *const names[] = {
+		[OTG_STATE_A_IDLE] = "a_idle",
+		[OTG_STATE_A_WAIT_VRISE] = "a_wait_vrise",
+		[OTG_STATE_A_WAIT_BCON] = "a_wait_bcon",
+		[OTG_STATE_A_HOST] = "a_host",
+		[OTG_STATE_A_SUSPEND] = "a_suspend",
+		[OTG_STATE_A_PERIPHERAL] = "a_peripheral",
+		[OTG_STATE_A_WAIT_VFALL] = "a_wait_vfall",
+		[OTG_STATE_A_VBUS_ERR] = "a_vbus_err",
+		[OTG_STATE_B_IDLE] = "b_idle",
+		[OTG_STATE_B_SRP_INIT] = "b_srp_init",
+		[OTG_STATE_B_PERIPHERAL] = "b_peripheral",
+		[OTG_STATE_B_WAIT_ACON] = "b_wait_acon",
+		[OTG_STATE_B_HOST] = "b_host",
+	};
+
+	if (state < 0 || state >= ARRAY_SIZE(names))
+		return "UNDEFINED";
+
+	return names[state];
+}
+
 /**
  * Check if the OTG device is in our wait list and return
  * otg_wait_data, else NULL.
@@ -433,7 +457,7 @@ static void drd_set_state(struct otg_fsm *fsm, enum usb_otg_state new_state)
 
 	fsm->state_changed = 1;
 	dev_dbg(otg->dev, "otg: set state: %s\n",
-		usb_otg_state_string(new_state));
+		otg_state_string(new_state));
 	switch (new_state) {
 	case OTG_STATE_B_IDLE:
 		drd_set_protocol(fsm, PROTO_UNDEF);
@@ -449,7 +473,7 @@ static void drd_set_state(struct otg_fsm *fsm, enum usb_otg_state new_state)
 		break;
 	default:
 		dev_warn(otg->dev, "%s: otg: invalid state: %s\n",
-			 __func__, usb_otg_state_string(new_state));
+			 __func__, otg_state_string(new_state));
 		break;
 	}
 
@@ -507,7 +531,7 @@ int drd_statemachine(struct usb_otg *otg)
 
 	default:
 		dev_err(otg->dev, "%s: otg: invalid usb-drd state: %s\n",
-			__func__, usb_otg_state_string(state));
+			__func__, otg_state_string(state));
 		break;
 	}
 
--
cheers,
-roger

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* Re: [PATCH v8 13/14] usb: gadget: udc: adapt to OTG core
  2016-05-16  8:26     ` Roger Quadros
@ 2016-05-16  9:23       ` Peter Chen
  2016-05-16  9:51         ` Roger Quadros
  0 siblings, 1 reply; 62+ messages in thread
From: Peter Chen @ 2016-05-16  9:23 UTC (permalink / raw)
  To: Roger Quadros
  Cc: peter.chen, balbi, tony, gregkh, dan.j.williams, mathias.nyman,
	Joao.Pinto, sergei.shtylyov, jun.li, grygorii.strashko,
	yoshihiro.shimoda.uh, robh, nsekhar, b-liu, linux-usb,
	linux-omap, linux-kernel, devicetree

On Mon, May 16, 2016 at 11:26:57AM +0300, Roger Quadros wrote:
> Hi,
> 
> On 16/05/16 10:02, Peter Chen wrote:
> > On Fri, May 13, 2016 at 01:03:27PM +0300, Roger Quadros wrote:
> >> +
> >> +static int usb_gadget_connect_control(struct usb_gadget *gadget, bool connect)
> >> +{
> >> +	struct usb_udc *udc;
> >> +
> >> +	mutex_lock(&udc_lock);
> >> +	udc = usb_gadget_to_udc(gadget);
> >> +	if (!udc) {
> >> +		dev_err(gadget->dev.parent, "%s: gadget not registered.\n",
> >> +			__func__);
> >> +		mutex_unlock(&udc_lock);
> >> +		return -EINVAL;
> >> +	}
> >> +
> >> +	if (connect) {
> >> +		if (!gadget->connected)
> >> +			usb_gadget_connect(udc->gadget);
> >> +	} else {
> >> +		if (gadget->connected) {
> >> +			usb_gadget_disconnect(udc->gadget);
> >> +			udc->driver->disconnect(udc->gadget);
> >> +		}
> >> +	}
> >> +
> >> +	mutex_unlock(&udc_lock);
> >> +
> >> +	return 0;
> >> +}
> >> +
> > 
> > Since this is called for vbus interrupt, why not using
> > usb_udc_vbus_handler directly, and call udc->driver->disconnect
> > at usb_gadget_stop.
> 
> We can't assume that this is always called for vbus interrupt so
> I decided not to call usb_udc_vbus_handler.
> 
> udc->vbus is really pointless for us. We keep vbus states in our
> state machine and leave udc->vbus as ture always.
> 
> Why do you want to move udc->driver->disconnect() to stop?
> If USB controller disconnected from bus then the gadget driver
> must be notified about the disconnect immediately. The controller
> may or may not be stopped by the core.
> 

Then, would you give some comments when this API will be used?
I was assumed it is only used for drd state machine.

> > 
> >>  	return 0;
> >> @@ -660,9 +830,15 @@ static ssize_t usb_udc_softconn_store(struct device *dev,
> >>  		return -EOPNOTSUPP;
> >>  	}
> >>  
> >> +	/* In OTG mode we don't support softconnect, but b_bus_req */
> >> +	if (udc->gadget->otg_dev) {
> >> +		dev_err(dev, "soft-connect not supported in OTG mode\n");
> >> +		return -EOPNOTSUPP;
> >> +	}
> >> +
> > 
> > The soft-connect can be supported at dual-role mode currently, we can
> > use b_bus_req entry once it is implemented later.
> 
> Soft-connect should be done via sysfs handling within the OTG core.
> This can be added later. I don't want anything outside the OTG core
> to handle soft-connect behaviour as it will be hard to keep things
> in sync.
> 
> I can update the comment to something like this.
> 
> /* In OTG/dual-role mode, soft-connect should be handled by OTG core */

Ok, let's Felipe decide it.

> 
> > 
> >>  	if (sysfs_streq(buf, "connect")) {
> >>  		usb_gadget_udc_start(udc);
> >> -		usb_gadget_connect(udc->gadget);
> >> +		usb_udc_connect_control(udc);
> > 
> > This line seems to be not related with this patch.
> > 
> Right. I'll remove it.
> 
> cheers,
> -roger

-- 

Best Regards,
Peter Chen

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v8 13/14] usb: gadget: udc: adapt to OTG core
  2016-05-16  9:23       ` Peter Chen
@ 2016-05-16  9:51         ` Roger Quadros
  2016-05-17  7:38           ` Jun Li
  2016-05-18  3:18           ` Peter Chen
  0 siblings, 2 replies; 62+ messages in thread
From: Roger Quadros @ 2016-05-16  9:51 UTC (permalink / raw)
  To: Peter Chen
  Cc: peter.chen, balbi, tony, gregkh, dan.j.williams, mathias.nyman,
	Joao.Pinto, sergei.shtylyov, jun.li, grygorii.strashko,
	yoshihiro.shimoda.uh, robh, nsekhar, b-liu, linux-usb,
	linux-omap, linux-kernel, devicetree

On 16/05/16 12:23, Peter Chen wrote:
> On Mon, May 16, 2016 at 11:26:57AM +0300, Roger Quadros wrote:
>> Hi,
>>
>> On 16/05/16 10:02, Peter Chen wrote:
>>> On Fri, May 13, 2016 at 01:03:27PM +0300, Roger Quadros wrote:
>>>> +
>>>> +static int usb_gadget_connect_control(struct usb_gadget *gadget, bool connect)
>>>> +{
>>>> +	struct usb_udc *udc;
>>>> +
>>>> +	mutex_lock(&udc_lock);
>>>> +	udc = usb_gadget_to_udc(gadget);
>>>> +	if (!udc) {
>>>> +		dev_err(gadget->dev.parent, "%s: gadget not registered.\n",
>>>> +			__func__);
>>>> +		mutex_unlock(&udc_lock);
>>>> +		return -EINVAL;
>>>> +	}
>>>> +
>>>> +	if (connect) {
>>>> +		if (!gadget->connected)
>>>> +			usb_gadget_connect(udc->gadget);
>>>> +	} else {
>>>> +		if (gadget->connected) {
>>>> +			usb_gadget_disconnect(udc->gadget);
>>>> +			udc->driver->disconnect(udc->gadget);
>>>> +		}
>>>> +	}
>>>> +
>>>> +	mutex_unlock(&udc_lock);
>>>> +
>>>> +	return 0;
>>>> +}
>>>> +
>>>
>>> Since this is called for vbus interrupt, why not using
>>> usb_udc_vbus_handler directly, and call udc->driver->disconnect
>>> at usb_gadget_stop.
>>
>> We can't assume that this is always called for vbus interrupt so
>> I decided not to call usb_udc_vbus_handler.
>>
>> udc->vbus is really pointless for us. We keep vbus states in our
>> state machine and leave udc->vbus as ture always.
>>
>> Why do you want to move udc->driver->disconnect() to stop?
>> If USB controller disconnected from bus then the gadget driver
>> must be notified about the disconnect immediately. The controller
>> may or may not be stopped by the core.
>>
> 
> Then, would you give some comments when this API will be used?
> I was assumed it is only used for drd state machine.

drd_state machine didn't even need this API in the first place :).
You guys wanted me to separate out start/stop and connect/disconnect for full OTG case.
Won't full OTG state machine want to use this API? If not what would it use?

cheers,
-roger

> 
>>>
>>>>  	return 0;
>>>> @@ -660,9 +830,15 @@ static ssize_t usb_udc_softconn_store(struct device *dev,
>>>>  		return -EOPNOTSUPP;
>>>>  	}
>>>>  
>>>> +	/* In OTG mode we don't support softconnect, but b_bus_req */
>>>> +	if (udc->gadget->otg_dev) {
>>>> +		dev_err(dev, "soft-connect not supported in OTG mode\n");
>>>> +		return -EOPNOTSUPP;
>>>> +	}
>>>> +
>>>
>>> The soft-connect can be supported at dual-role mode currently, we can
>>> use b_bus_req entry once it is implemented later.
>>
>> Soft-connect should be done via sysfs handling within the OTG core.
>> This can be added later. I don't want anything outside the OTG core
>> to handle soft-connect behaviour as it will be hard to keep things
>> in sync.
>>
>> I can update the comment to something like this.
>>
>> /* In OTG/dual-role mode, soft-connect should be handled by OTG core */
> 
> Ok, let's Felipe decide it.
> 
>>
>>>
>>>>  	if (sysfs_streq(buf, "connect")) {
>>>>  		usb_gadget_udc_start(udc);
>>>> -		usb_gadget_connect(udc->gadget);
>>>> +		usb_udc_connect_control(udc);
>>>
>>> This line seems to be not related with this patch.
>>>
>> Right. I'll remove it.
>>
>> cheers,
>> -roger
> 

^ permalink raw reply	[flat|nested] 62+ messages in thread

* RE: [PATCH v8 13/14] usb: gadget: udc: adapt to OTG core
  2016-05-16  9:51         ` Roger Quadros
@ 2016-05-17  7:38           ` Jun Li
  2016-05-17  8:08             ` Roger Quadros
  2016-05-18  3:18           ` Peter Chen
  1 sibling, 1 reply; 62+ messages in thread
From: Jun Li @ 2016-05-17  7:38 UTC (permalink / raw)
  To: Roger Quadros, Peter Chen
  Cc: peter.chen, balbi, tony, gregkh, dan.j.williams, mathias.nyman,
	Joao.Pinto, sergei.shtylyov, jun.li, grygorii.strashko,
	yoshihiro.shimoda.uh, robh, nsekhar, b-liu, linux-usb,
	linux-omap, linux-kernel, devicetree

Hi

> -----Original Message-----
> From: Roger Quadros [mailto:rogerq@ti.com]
> Sent: Monday, May 16, 2016 5:52 PM
> To: Peter Chen <hzpeterchen@gmail.com>
> Cc: peter.chen@freescale.com; balbi@kernel.org; tony@atomide.com;
> gregkh@linuxfoundation.org; dan.j.williams@intel.com;
> mathias.nyman@linux.intel.com; Joao.Pinto@synopsys.com;
> sergei.shtylyov@cogentembedded.com; jun.li@freescale.com;
> grygorii.strashko@ti.com; yoshihiro.shimoda.uh@renesas.com;
> robh@kernel.org; nsekhar@ti.com; b-liu@ti.com; linux-usb@vger.kernel.org;
> linux-omap@vger.kernel.org; linux-kernel@vger.kernel.org;
> devicetree@vger.kernel.org
> Subject: Re: [PATCH v8 13/14] usb: gadget: udc: adapt to OTG core
> 
> On 16/05/16 12:23, Peter Chen wrote:
> > On Mon, May 16, 2016 at 11:26:57AM +0300, Roger Quadros wrote:
> >> Hi,
> >>
> >> On 16/05/16 10:02, Peter Chen wrote:
> >>> On Fri, May 13, 2016 at 01:03:27PM +0300, Roger Quadros wrote:
> >>>> +
> >>>> +static int usb_gadget_connect_control(struct usb_gadget *gadget,
> >>>> +bool connect) {
> >>>> +	struct usb_udc *udc;
> >>>> +
> >>>> +	mutex_lock(&udc_lock);
> >>>> +	udc = usb_gadget_to_udc(gadget);
> >>>> +	if (!udc) {
> >>>> +		dev_err(gadget->dev.parent, "%s: gadget not
> registered.\n",
> >>>> +			__func__);
> >>>> +		mutex_unlock(&udc_lock);
> >>>> +		return -EINVAL;
> >>>> +	}
> >>>> +
> >>>> +	if (connect) {
> >>>> +		if (!gadget->connected)
> >>>> +			usb_gadget_connect(udc->gadget);
> >>>> +	} else {
> >>>> +		if (gadget->connected) {
> >>>> +			usb_gadget_disconnect(udc->gadget);
> >>>> +			udc->driver->disconnect(udc->gadget);
> >>>> +		}
> >>>> +	}
> >>>> +
> >>>> +	mutex_unlock(&udc_lock);
> >>>> +
> >>>> +	return 0;
> >>>> +}
> >>>> +
> >>>
> >>> Since this is called for vbus interrupt, why not using
> >>> usb_udc_vbus_handler directly, and call udc->driver->disconnect at
> >>> usb_gadget_stop.
> >>
> >> We can't assume that this is always called for vbus interrupt so I
> >> decided not to call usb_udc_vbus_handler.
> >>
> >> udc->vbus is really pointless for us. We keep vbus states in our
> >> state machine and leave udc->vbus as ture always.
> >>
> >> Why do you want to move udc->driver->disconnect() to stop?
> >> If USB controller disconnected from bus then the gadget driver must
> >> be notified about the disconnect immediately. The controller may or
> >> may not be stopped by the core.
> >>
> >
> > Then, would you give some comments when this API will be used?
> > I was assumed it is only used for drd state machine.
> 
> drd_state machine didn't even need this API in the first place :).
> You guys wanted me to separate out start/stop and connect/disconnect for
> full OTG case.
> Won't full OTG state machine want to use this API? If not what would it
> use?

Instead create those new interfaces/symbol here and there just aim to
address build problems in diff configures, Could we only allow meaningful
combination of those 3 drivers configures?

Hcd=y, gadget=y, otg=y or
Hcd=m, gadget=m, otg=m

Li Jun

> 
> cheers,
> -roger
> 
> >
> >>>
> >>>>  	return 0;
> >>>> @@ -660,9 +830,15 @@ static ssize_t usb_udc_softconn_store(struct
> device *dev,
> >>>>  		return -EOPNOTSUPP;
> >>>>  	}
> >>>>
> >>>> +	/* In OTG mode we don't support softconnect, but b_bus_req */
> >>>> +	if (udc->gadget->otg_dev) {
> >>>> +		dev_err(dev, "soft-connect not supported in OTG mode\n");
> >>>> +		return -EOPNOTSUPP;
> >>>> +	}
> >>>> +
> >>>
> >>> The soft-connect can be supported at dual-role mode currently, we
> >>> can use b_bus_req entry once it is implemented later.
> >>
> >> Soft-connect should be done via sysfs handling within the OTG core.
> >> This can be added later. I don't want anything outside the OTG core
> >> to handle soft-connect behaviour as it will be hard to keep things in
> >> sync.
> >>
> >> I can update the comment to something like this.
> >>
> >> /* In OTG/dual-role mode, soft-connect should be handled by OTG core
> >> */
> >
> > Ok, let's Felipe decide it.
> >
> >>
> >>>
> >>>>  	if (sysfs_streq(buf, "connect")) {
> >>>>  		usb_gadget_udc_start(udc);
> >>>> -		usb_gadget_connect(udc->gadget);
> >>>> +		usb_udc_connect_control(udc);
> >>>
> >>> This line seems to be not related with this patch.
> >>>
> >> Right. I'll remove it.
> >>
> >> cheers,
> >> -roger
> >

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v8 13/14] usb: gadget: udc: adapt to OTG core
  2016-05-17  7:38           ` Jun Li
@ 2016-05-17  8:08             ` Roger Quadros
  2016-05-17  8:28               ` Jun Li
  0 siblings, 1 reply; 62+ messages in thread
From: Roger Quadros @ 2016-05-17  8:08 UTC (permalink / raw)
  To: Jun Li, Peter Chen
  Cc: peter.chen, balbi, tony, gregkh, dan.j.williams, mathias.nyman,
	Joao.Pinto, sergei.shtylyov, jun.li, grygorii.strashko,
	yoshihiro.shimoda.uh, robh, nsekhar, b-liu, linux-usb,
	linux-omap, linux-kernel, devicetree

On 17/05/16 10:38, Jun Li wrote:
> Hi
> 
>> -----Original Message-----
>> From: Roger Quadros [mailto:rogerq@ti.com]
>> Sent: Monday, May 16, 2016 5:52 PM
>> To: Peter Chen <hzpeterchen@gmail.com>
>> Cc: peter.chen@freescale.com; balbi@kernel.org; tony@atomide.com;
>> gregkh@linuxfoundation.org; dan.j.williams@intel.com;
>> mathias.nyman@linux.intel.com; Joao.Pinto@synopsys.com;
>> sergei.shtylyov@cogentembedded.com; jun.li@freescale.com;
>> grygorii.strashko@ti.com; yoshihiro.shimoda.uh@renesas.com;
>> robh@kernel.org; nsekhar@ti.com; b-liu@ti.com; linux-usb@vger.kernel.org;
>> linux-omap@vger.kernel.org; linux-kernel@vger.kernel.org;
>> devicetree@vger.kernel.org
>> Subject: Re: [PATCH v8 13/14] usb: gadget: udc: adapt to OTG core
>>
>> On 16/05/16 12:23, Peter Chen wrote:
>>> On Mon, May 16, 2016 at 11:26:57AM +0300, Roger Quadros wrote:
>>>> Hi,
>>>>
>>>> On 16/05/16 10:02, Peter Chen wrote:
>>>>> On Fri, May 13, 2016 at 01:03:27PM +0300, Roger Quadros wrote:
>>>>>> +
>>>>>> +static int usb_gadget_connect_control(struct usb_gadget *gadget,
>>>>>> +bool connect) {
>>>>>> +	struct usb_udc *udc;
>>>>>> +
>>>>>> +	mutex_lock(&udc_lock);
>>>>>> +	udc = usb_gadget_to_udc(gadget);
>>>>>> +	if (!udc) {
>>>>>> +		dev_err(gadget->dev.parent, "%s: gadget not
>> registered.\n",
>>>>>> +			__func__);
>>>>>> +		mutex_unlock(&udc_lock);
>>>>>> +		return -EINVAL;
>>>>>> +	}
>>>>>> +
>>>>>> +	if (connect) {
>>>>>> +		if (!gadget->connected)
>>>>>> +			usb_gadget_connect(udc->gadget);
>>>>>> +	} else {
>>>>>> +		if (gadget->connected) {
>>>>>> +			usb_gadget_disconnect(udc->gadget);
>>>>>> +			udc->driver->disconnect(udc->gadget);
>>>>>> +		}
>>>>>> +	}
>>>>>> +
>>>>>> +	mutex_unlock(&udc_lock);
>>>>>> +
>>>>>> +	return 0;
>>>>>> +}
>>>>>> +
>>>>>
>>>>> Since this is called for vbus interrupt, why not using
>>>>> usb_udc_vbus_handler directly, and call udc->driver->disconnect at
>>>>> usb_gadget_stop.
>>>>
>>>> We can't assume that this is always called for vbus interrupt so I
>>>> decided not to call usb_udc_vbus_handler.
>>>>
>>>> udc->vbus is really pointless for us. We keep vbus states in our
>>>> state machine and leave udc->vbus as ture always.
>>>>
>>>> Why do you want to move udc->driver->disconnect() to stop?
>>>> If USB controller disconnected from bus then the gadget driver must
>>>> be notified about the disconnect immediately. The controller may or
>>>> may not be stopped by the core.
>>>>
>>>
>>> Then, would you give some comments when this API will be used?
>>> I was assumed it is only used for drd state machine.
>>
>> drd_state machine didn't even need this API in the first place :).
>> You guys wanted me to separate out start/stop and connect/disconnect for
>> full OTG case.
>> Won't full OTG state machine want to use this API? If not what would it
>> use?
> 
> Instead create those new interfaces/symbol here and there just aim to
> address build problems in diff configures, Could we only allow meaningful
> combination of those 3 drivers configures?
> 
> Hcd=y, gadget=y, otg=y or
> Hcd=m, gadget=m, otg=m

This is still a limitation.

It is perfectly fine to have
hcd=m, gadget=y
or
hcd=y, gadget=m

cheers,
-roger

> 
> Li Jun
> 
>>
>> cheers,
>> -roger
>>
>>>
>>>>>
>>>>>>  	return 0;
>>>>>> @@ -660,9 +830,15 @@ static ssize_t usb_udc_softconn_store(struct
>> device *dev,
>>>>>>  		return -EOPNOTSUPP;
>>>>>>  	}
>>>>>>
>>>>>> +	/* In OTG mode we don't support softconnect, but b_bus_req */
>>>>>> +	if (udc->gadget->otg_dev) {
>>>>>> +		dev_err(dev, "soft-connect not supported in OTG mode\n");
>>>>>> +		return -EOPNOTSUPP;
>>>>>> +	}
>>>>>> +
>>>>>
>>>>> The soft-connect can be supported at dual-role mode currently, we
>>>>> can use b_bus_req entry once it is implemented later.
>>>>
>>>> Soft-connect should be done via sysfs handling within the OTG core.
>>>> This can be added later. I don't want anything outside the OTG core
>>>> to handle soft-connect behaviour as it will be hard to keep things in
>>>> sync.
>>>>
>>>> I can update the comment to something like this.
>>>>
>>>> /* In OTG/dual-role mode, soft-connect should be handled by OTG core
>>>> */
>>>
>>> Ok, let's Felipe decide it.
>>>
>>>>
>>>>>
>>>>>>  	if (sysfs_streq(buf, "connect")) {
>>>>>>  		usb_gadget_udc_start(udc);
>>>>>> -		usb_gadget_connect(udc->gadget);
>>>>>> +		usb_udc_connect_control(udc);
>>>>>
>>>>> This line seems to be not related with this patch.
>>>>>
>>>> Right. I'll remove it.
>>>>
>>>> cheers,
>>>> -roger
>>>

^ permalink raw reply	[flat|nested] 62+ messages in thread

* RE: [PATCH v8 13/14] usb: gadget: udc: adapt to OTG core
  2016-05-17  8:08             ` Roger Quadros
@ 2016-05-17  8:28               ` Jun Li
  2016-05-18 12:42                 ` Roger Quadros
  0 siblings, 1 reply; 62+ messages in thread
From: Jun Li @ 2016-05-17  8:28 UTC (permalink / raw)
  To: Roger Quadros, Peter Chen
  Cc: peter.chen, balbi, tony, gregkh, dan.j.williams, mathias.nyman,
	Joao.Pinto, sergei.shtylyov, jun.li, grygorii.strashko,
	yoshihiro.shimoda.uh, robh, nsekhar, b-liu, linux-usb,
	linux-omap, linux-kernel, devicetree

Hi Roger,

> -----Original Message-----
> From: Roger Quadros [mailto:rogerq@ti.com]
> Sent: Tuesday, May 17, 2016 4:09 PM
> To: Jun Li <jun.li@nxp.com>; Peter Chen <hzpeterchen@gmail.com>
> Cc: peter.chen@freescale.com; balbi@kernel.org; tony@atomide.com;
> gregkh@linuxfoundation.org; dan.j.williams@intel.com;
> mathias.nyman@linux.intel.com; Joao.Pinto@synopsys.com;
> sergei.shtylyov@cogentembedded.com; jun.li@freescale.com;
> grygorii.strashko@ti.com; yoshihiro.shimoda.uh@renesas.com;
> robh@kernel.org; nsekhar@ti.com; b-liu@ti.com; linux-usb@vger.kernel.org;
> linux-omap@vger.kernel.org; linux-kernel@vger.kernel.org;
> devicetree@vger.kernel.org
> Subject: Re: [PATCH v8 13/14] usb: gadget: udc: adapt to OTG core
> 
> On 17/05/16 10:38, Jun Li wrote:
> > Hi
> >
> >> -----Original Message-----
> >> From: Roger Quadros [mailto:rogerq@ti.com]
> >> Sent: Monday, May 16, 2016 5:52 PM
> >> To: Peter Chen <hzpeterchen@gmail.com>
> >> Cc: peter.chen@freescale.com; balbi@kernel.org; tony@atomide.com;
> >> gregkh@linuxfoundation.org; dan.j.williams@intel.com;
> >> mathias.nyman@linux.intel.com; Joao.Pinto@synopsys.com;
> >> sergei.shtylyov@cogentembedded.com; jun.li@freescale.com;
> >> grygorii.strashko@ti.com; yoshihiro.shimoda.uh@renesas.com;
> >> robh@kernel.org; nsekhar@ti.com; b-liu@ti.com;
> >> linux-usb@vger.kernel.org; linux-omap@vger.kernel.org;
> >> linux-kernel@vger.kernel.org; devicetree@vger.kernel.org
> >> Subject: Re: [PATCH v8 13/14] usb: gadget: udc: adapt to OTG core
> >>
> >> On 16/05/16 12:23, Peter Chen wrote:
> >>> On Mon, May 16, 2016 at 11:26:57AM +0300, Roger Quadros wrote:
> >>>> Hi,
> >>>>
> >>>> On 16/05/16 10:02, Peter Chen wrote:
> >>>>> On Fri, May 13, 2016 at 01:03:27PM +0300, Roger Quadros wrote:
> >>>>>> +
> >>>>>> +static int usb_gadget_connect_control(struct usb_gadget *gadget,
> >>>>>> +bool connect) {
> >>>>>> +	struct usb_udc *udc;
> >>>>>> +
> >>>>>> +	mutex_lock(&udc_lock);
> >>>>>> +	udc = usb_gadget_to_udc(gadget);
> >>>>>> +	if (!udc) {
> >>>>>> +		dev_err(gadget->dev.parent, "%s: gadget not
> >> registered.\n",
> >>>>>> +			__func__);
> >>>>>> +		mutex_unlock(&udc_lock);
> >>>>>> +		return -EINVAL;
> >>>>>> +	}
> >>>>>> +
> >>>>>> +	if (connect) {
> >>>>>> +		if (!gadget->connected)
> >>>>>> +			usb_gadget_connect(udc->gadget);
> >>>>>> +	} else {
> >>>>>> +		if (gadget->connected) {
> >>>>>> +			usb_gadget_disconnect(udc->gadget);
> >>>>>> +			udc->driver->disconnect(udc->gadget);
> >>>>>> +		}
> >>>>>> +	}
> >>>>>> +
> >>>>>> +	mutex_unlock(&udc_lock);
> >>>>>> +
> >>>>>> +	return 0;
> >>>>>> +}
> >>>>>> +
> >>>>>
> >>>>> Since this is called for vbus interrupt, why not using
> >>>>> usb_udc_vbus_handler directly, and call udc->driver->disconnect at
> >>>>> usb_gadget_stop.
> >>>>
> >>>> We can't assume that this is always called for vbus interrupt so I
> >>>> decided not to call usb_udc_vbus_handler.
> >>>>
> >>>> udc->vbus is really pointless for us. We keep vbus states in our
> >>>> state machine and leave udc->vbus as ture always.
> >>>>
> >>>> Why do you want to move udc->driver->disconnect() to stop?
> >>>> If USB controller disconnected from bus then the gadget driver must
> >>>> be notified about the disconnect immediately. The controller may or
> >>>> may not be stopped by the core.
> >>>>
> >>>
> >>> Then, would you give some comments when this API will be used?
> >>> I was assumed it is only used for drd state machine.
> >>
> >> drd_state machine didn't even need this API in the first place :).
> >> You guys wanted me to separate out start/stop and connect/disconnect
> >> for full OTG case.
> >> Won't full OTG state machine want to use this API? If not what would
> >> it use?
> >
> > Instead create those new interfaces/symbol here and there just aim to
> > address build problems in diff configures, Could we only allow
> > meaningful combination of those 3 drivers configures?
> >
> > Hcd=y, gadget=y, otg=y or
> > Hcd=m, gadget=m, otg=m
> 
> This is still a limitation.
> 
> It is perfectly fine to have
> hcd=m, gadget=y
> or
> hcd=y, gadget=m

I agree it makes sense to have above configs in non-otg case, that is,
the 'y' driver can work without 'm' driver loaded.

But,
in otg enabled(y/m) case, the otherwise config of my list can't make
any sense from my point view. That is: some driver is built-in, but
it can't work at all if another 'm' driver is not loaded,

in another words, the otg driver has to be 'm' if its dependent driver
is 'm', correct?    

Li Jun

> 
> cheers,
> -roger
> 
> >
> > Li Jun
> >
> >>
> >> cheers,
> >> -roger
> >>
> >>>
> >>>>>
> >>>>>>  	return 0;
> >>>>>> @@ -660,9 +830,15 @@ static ssize_t usb_udc_softconn_store(struct
> >> device *dev,
> >>>>>>  		return -EOPNOTSUPP;
> >>>>>>  	}
> >>>>>>
> >>>>>> +	/* In OTG mode we don't support softconnect, but b_bus_req */
> >>>>>> +	if (udc->gadget->otg_dev) {
> >>>>>> +		dev_err(dev, "soft-connect not supported in OTG mode\n");
> >>>>>> +		return -EOPNOTSUPP;
> >>>>>> +	}
> >>>>>> +
> >>>>>
> >>>>> The soft-connect can be supported at dual-role mode currently, we
> >>>>> can use b_bus_req entry once it is implemented later.
> >>>>
> >>>> Soft-connect should be done via sysfs handling within the OTG core.
> >>>> This can be added later. I don't want anything outside the OTG core
> >>>> to handle soft-connect behaviour as it will be hard to keep things
> >>>> in sync.
> >>>>
> >>>> I can update the comment to something like this.
> >>>>
> >>>> /* In OTG/dual-role mode, soft-connect should be handled by OTG
> >>>> core */
> >>>
> >>> Ok, let's Felipe decide it.
> >>>
> >>>>
> >>>>>
> >>>>>>  	if (sysfs_streq(buf, "connect")) {
> >>>>>>  		usb_gadget_udc_start(udc);
> >>>>>> -		usb_gadget_connect(udc->gadget);
> >>>>>> +		usb_udc_connect_control(udc);
> >>>>>
> >>>>> This line seems to be not related with this patch.
> >>>>>
> >>>> Right. I'll remove it.
> >>>>
> >>>> cheers,
> >>>> -roger
> >>>

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v8 13/14] usb: gadget: udc: adapt to OTG core
  2016-05-16  9:51         ` Roger Quadros
  2016-05-17  7:38           ` Jun Li
@ 2016-05-18  3:18           ` Peter Chen
  2016-05-18 12:45             ` Roger Quadros
  1 sibling, 1 reply; 62+ messages in thread
From: Peter Chen @ 2016-05-18  3:18 UTC (permalink / raw)
  To: Roger Quadros
  Cc: peter.chen, balbi, tony, gregkh, dan.j.williams, mathias.nyman,
	Joao.Pinto, sergei.shtylyov, jun.li, grygorii.strashko,
	yoshihiro.shimoda.uh, robh, nsekhar, b-liu, linux-usb,
	linux-omap, linux-kernel, devicetree

On Mon, May 16, 2016 at 12:51:53PM +0300, Roger Quadros wrote:
> On 16/05/16 12:23, Peter Chen wrote:
> > On Mon, May 16, 2016 at 11:26:57AM +0300, Roger Quadros wrote:
> >> Hi,
> >>
> >> On 16/05/16 10:02, Peter Chen wrote:
> >>> On Fri, May 13, 2016 at 01:03:27PM +0300, Roger Quadros wrote:
> >>>> +
> >>>> +static int usb_gadget_connect_control(struct usb_gadget *gadget, bool connect)
> >>>> +{
> >>>> +	struct usb_udc *udc;
> >>>> +
> >>>> +	mutex_lock(&udc_lock);
> >>>> +	udc = usb_gadget_to_udc(gadget);
> >>>> +	if (!udc) {
> >>>> +		dev_err(gadget->dev.parent, "%s: gadget not registered.\n",
> >>>> +			__func__);
> >>>> +		mutex_unlock(&udc_lock);
> >>>> +		return -EINVAL;
> >>>> +	}
> >>>> +
> >>>> +	if (connect) {
> >>>> +		if (!gadget->connected)
> >>>> +			usb_gadget_connect(udc->gadget);
> >>>> +	} else {
> >>>> +		if (gadget->connected) {
> >>>> +			usb_gadget_disconnect(udc->gadget);
> >>>> +			udc->driver->disconnect(udc->gadget);
> >>>> +		}
> >>>> +	}
> >>>> +
> >>>> +	mutex_unlock(&udc_lock);
> >>>> +
> >>>> +	return 0;
> >>>> +}
> >>>> +
> >>>
> >>> Since this is called for vbus interrupt, why not using
> >>> usb_udc_vbus_handler directly, and call udc->driver->disconnect
> >>> at usb_gadget_stop.
> >>
> >> We can't assume that this is always called for vbus interrupt so
> >> I decided not to call usb_udc_vbus_handler.
> >>
> >> udc->vbus is really pointless for us. We keep vbus states in our
> >> state machine and leave udc->vbus as ture always.
> >>
> >> Why do you want to move udc->driver->disconnect() to stop?
> >> If USB controller disconnected from bus then the gadget driver
> >> must be notified about the disconnect immediately. The controller
> >> may or may not be stopped by the core.
> >>
> > 
> > Then, would you give some comments when this API will be used?
> > I was assumed it is only used for drd state machine.
> 
> drd_state machine didn't even need this API in the first place :).
> You guys wanted me to separate out start/stop and connect/disconnect for full OTG case.
> Won't full OTG state machine want to use this API? If not what would it use?
> 

Oh, I meant only drd and fully otg state machine needs it. I am
wondering if we need have a new API to do it. Two questions:

- Except for vbus interrupt, any chances this API will be used at
current logic?
- When this API is called but without a coming gadget->stop?

-- 

Best Regards,
Peter Chen

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v8 13/14] usb: gadget: udc: adapt to OTG core
  2016-05-17  8:28               ` Jun Li
@ 2016-05-18 12:42                 ` Roger Quadros
  2016-05-18 13:12                   ` Jun Li
  0 siblings, 1 reply; 62+ messages in thread
From: Roger Quadros @ 2016-05-18 12:42 UTC (permalink / raw)
  To: Jun Li, Peter Chen
  Cc: peter.chen, balbi, tony, gregkh, dan.j.williams, mathias.nyman,
	Joao.Pinto, sergei.shtylyov, jun.li, grygorii.strashko,
	yoshihiro.shimoda.uh, robh, nsekhar, b-liu, linux-usb,
	linux-omap, linux-kernel, devicetree

On 17/05/16 11:28, Jun Li wrote:
> Hi Roger,
> 
>> -----Original Message-----
>> From: Roger Quadros [mailto:rogerq@ti.com]
>> Sent: Tuesday, May 17, 2016 4:09 PM
>> To: Jun Li <jun.li@nxp.com>; Peter Chen <hzpeterchen@gmail.com>
>> Cc: peter.chen@freescale.com; balbi@kernel.org; tony@atomide.com;
>> gregkh@linuxfoundation.org; dan.j.williams@intel.com;
>> mathias.nyman@linux.intel.com; Joao.Pinto@synopsys.com;
>> sergei.shtylyov@cogentembedded.com; jun.li@freescale.com;
>> grygorii.strashko@ti.com; yoshihiro.shimoda.uh@renesas.com;
>> robh@kernel.org; nsekhar@ti.com; b-liu@ti.com; linux-usb@vger.kernel.org;
>> linux-omap@vger.kernel.org; linux-kernel@vger.kernel.org;
>> devicetree@vger.kernel.org
>> Subject: Re: [PATCH v8 13/14] usb: gadget: udc: adapt to OTG core
>>
>> On 17/05/16 10:38, Jun Li wrote:
>>> Hi
>>>
>>>> -----Original Message-----
>>>> From: Roger Quadros [mailto:rogerq@ti.com]
>>>> Sent: Monday, May 16, 2016 5:52 PM
>>>> To: Peter Chen <hzpeterchen@gmail.com>
>>>> Cc: peter.chen@freescale.com; balbi@kernel.org; tony@atomide.com;
>>>> gregkh@linuxfoundation.org; dan.j.williams@intel.com;
>>>> mathias.nyman@linux.intel.com; Joao.Pinto@synopsys.com;
>>>> sergei.shtylyov@cogentembedded.com; jun.li@freescale.com;
>>>> grygorii.strashko@ti.com; yoshihiro.shimoda.uh@renesas.com;
>>>> robh@kernel.org; nsekhar@ti.com; b-liu@ti.com;
>>>> linux-usb@vger.kernel.org; linux-omap@vger.kernel.org;
>>>> linux-kernel@vger.kernel.org; devicetree@vger.kernel.org
>>>> Subject: Re: [PATCH v8 13/14] usb: gadget: udc: adapt to OTG core
>>>>
>>>> On 16/05/16 12:23, Peter Chen wrote:
>>>>> On Mon, May 16, 2016 at 11:26:57AM +0300, Roger Quadros wrote:
>>>>>> Hi,
>>>>>>
>>>>>> On 16/05/16 10:02, Peter Chen wrote:
>>>>>>> On Fri, May 13, 2016 at 01:03:27PM +0300, Roger Quadros wrote:
>>>>>>>> +
>>>>>>>> +static int usb_gadget_connect_control(struct usb_gadget *gadget,
>>>>>>>> +bool connect) {
>>>>>>>> +	struct usb_udc *udc;
>>>>>>>> +
>>>>>>>> +	mutex_lock(&udc_lock);
>>>>>>>> +	udc = usb_gadget_to_udc(gadget);
>>>>>>>> +	if (!udc) {
>>>>>>>> +		dev_err(gadget->dev.parent, "%s: gadget not
>>>> registered.\n",
>>>>>>>> +			__func__);
>>>>>>>> +		mutex_unlock(&udc_lock);
>>>>>>>> +		return -EINVAL;
>>>>>>>> +	}
>>>>>>>> +
>>>>>>>> +	if (connect) {
>>>>>>>> +		if (!gadget->connected)
>>>>>>>> +			usb_gadget_connect(udc->gadget);
>>>>>>>> +	} else {
>>>>>>>> +		if (gadget->connected) {
>>>>>>>> +			usb_gadget_disconnect(udc->gadget);
>>>>>>>> +			udc->driver->disconnect(udc->gadget);
>>>>>>>> +		}
>>>>>>>> +	}
>>>>>>>> +
>>>>>>>> +	mutex_unlock(&udc_lock);
>>>>>>>> +
>>>>>>>> +	return 0;
>>>>>>>> +}
>>>>>>>> +
>>>>>>>
>>>>>>> Since this is called for vbus interrupt, why not using
>>>>>>> usb_udc_vbus_handler directly, and call udc->driver->disconnect at
>>>>>>> usb_gadget_stop.
>>>>>>
>>>>>> We can't assume that this is always called for vbus interrupt so I
>>>>>> decided not to call usb_udc_vbus_handler.
>>>>>>
>>>>>> udc->vbus is really pointless for us. We keep vbus states in our
>>>>>> state machine and leave udc->vbus as ture always.
>>>>>>
>>>>>> Why do you want to move udc->driver->disconnect() to stop?
>>>>>> If USB controller disconnected from bus then the gadget driver must
>>>>>> be notified about the disconnect immediately. The controller may or
>>>>>> may not be stopped by the core.
>>>>>>
>>>>>
>>>>> Then, would you give some comments when this API will be used?
>>>>> I was assumed it is only used for drd state machine.
>>>>
>>>> drd_state machine didn't even need this API in the first place :).
>>>> You guys wanted me to separate out start/stop and connect/disconnect
>>>> for full OTG case.
>>>> Won't full OTG state machine want to use this API? If not what would
>>>> it use?
>>>
>>> Instead create those new interfaces/symbol here and there just aim to
>>> address build problems in diff configures, Could we only allow
>>> meaningful combination of those 3 drivers configures?
>>>
>>> Hcd=y, gadget=y, otg=y or
>>> Hcd=m, gadget=m, otg=m
>>
>> This is still a limitation.
>>
>> It is perfectly fine to have
>> hcd=m, gadget=y
>> or
>> hcd=y, gadget=m
> 
> I agree it makes sense to have above configs in non-otg case, that is,
> the 'y' driver can work without 'm' driver loaded.
> 
> But,
> in otg enabled(y/m) case, the otherwise config of my list can't make
> any sense from my point view. That is: some driver is built-in, but
> it can't work at all if another 'm' driver is not loaded,
> 
> in another words, the otg driver has to be 'm' if its dependent driver
> is 'm', correct?

If both host and gadget are 'm' then otg can be 'm', but if either host or
gadget is built in then we have no choice but to make otg as built-in.

I didn't want to have complex Kconfig so decided to have otg as built-in only.
What do you want me to change in existing code? and why?

cheers,
-roger
    
> 
> Li Jun
> 
>>
>> cheers,
>> -roger
>>
>>>
>>> Li Jun
>>>
>>>>
>>>> cheers,
>>>> -roger
>>>>
>>>>>
>>>>>>>
>>>>>>>>  	return 0;
>>>>>>>> @@ -660,9 +830,15 @@ static ssize_t usb_udc_softconn_store(struct
>>>> device *dev,
>>>>>>>>  		return -EOPNOTSUPP;
>>>>>>>>  	}
>>>>>>>>
>>>>>>>> +	/* In OTG mode we don't support softconnect, but b_bus_req */
>>>>>>>> +	if (udc->gadget->otg_dev) {
>>>>>>>> +		dev_err(dev, "soft-connect not supported in OTG mode\n");
>>>>>>>> +		return -EOPNOTSUPP;
>>>>>>>> +	}
>>>>>>>> +
>>>>>>>
>>>>>>> The soft-connect can be supported at dual-role mode currently, we
>>>>>>> can use b_bus_req entry once it is implemented later.
>>>>>>
>>>>>> Soft-connect should be done via sysfs handling within the OTG core.
>>>>>> This can be added later. I don't want anything outside the OTG core
>>>>>> to handle soft-connect behaviour as it will be hard to keep things
>>>>>> in sync.
>>>>>>
>>>>>> I can update the comment to something like this.
>>>>>>
>>>>>> /* In OTG/dual-role mode, soft-connect should be handled by OTG
>>>>>> core */
>>>>>
>>>>> Ok, let's Felipe decide it.
>>>>>
>>>>>>
>>>>>>>
>>>>>>>>  	if (sysfs_streq(buf, "connect")) {
>>>>>>>>  		usb_gadget_udc_start(udc);
>>>>>>>> -		usb_gadget_connect(udc->gadget);
>>>>>>>> +		usb_udc_connect_control(udc);
>>>>>>>
>>>>>>> This line seems to be not related with this patch.
>>>>>>>
>>>>>> Right. I'll remove it.
>>>>>>
>>>>>> cheers,
>>>>>> -roger
>>>>>

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v8 13/14] usb: gadget: udc: adapt to OTG core
  2016-05-18  3:18           ` Peter Chen
@ 2016-05-18 12:45             ` Roger Quadros
  2016-05-20  1:39               ` Peter Chen
  0 siblings, 1 reply; 62+ messages in thread
From: Roger Quadros @ 2016-05-18 12:45 UTC (permalink / raw)
  To: Peter Chen
  Cc: peter.chen, balbi, tony, gregkh, dan.j.williams, mathias.nyman,
	Joao.Pinto, sergei.shtylyov, jun.li, grygorii.strashko,
	yoshihiro.shimoda.uh, robh, nsekhar, b-liu, linux-usb,
	linux-omap, linux-kernel, devicetree

On 18/05/16 06:18, Peter Chen wrote:
> On Mon, May 16, 2016 at 12:51:53PM +0300, Roger Quadros wrote:
>> On 16/05/16 12:23, Peter Chen wrote:
>>> On Mon, May 16, 2016 at 11:26:57AM +0300, Roger Quadros wrote:
>>>> Hi,
>>>>
>>>> On 16/05/16 10:02, Peter Chen wrote:
>>>>> On Fri, May 13, 2016 at 01:03:27PM +0300, Roger Quadros wrote:
>>>>>> +
>>>>>> +static int usb_gadget_connect_control(struct usb_gadget *gadget, bool connect)
>>>>>> +{
>>>>>> +	struct usb_udc *udc;
>>>>>> +
>>>>>> +	mutex_lock(&udc_lock);
>>>>>> +	udc = usb_gadget_to_udc(gadget);
>>>>>> +	if (!udc) {
>>>>>> +		dev_err(gadget->dev.parent, "%s: gadget not registered.\n",
>>>>>> +			__func__);
>>>>>> +		mutex_unlock(&udc_lock);
>>>>>> +		return -EINVAL;
>>>>>> +	}
>>>>>> +
>>>>>> +	if (connect) {
>>>>>> +		if (!gadget->connected)
>>>>>> +			usb_gadget_connect(udc->gadget);
>>>>>> +	} else {
>>>>>> +		if (gadget->connected) {
>>>>>> +			usb_gadget_disconnect(udc->gadget);
>>>>>> +			udc->driver->disconnect(udc->gadget);
>>>>>> +		}
>>>>>> +	}
>>>>>> +
>>>>>> +	mutex_unlock(&udc_lock);
>>>>>> +
>>>>>> +	return 0;
>>>>>> +}
>>>>>> +
>>>>>
>>>>> Since this is called for vbus interrupt, why not using
>>>>> usb_udc_vbus_handler directly, and call udc->driver->disconnect
>>>>> at usb_gadget_stop.
>>>>
>>>> We can't assume that this is always called for vbus interrupt so
>>>> I decided not to call usb_udc_vbus_handler.
>>>>
>>>> udc->vbus is really pointless for us. We keep vbus states in our
>>>> state machine and leave udc->vbus as ture always.
>>>>
>>>> Why do you want to move udc->driver->disconnect() to stop?
>>>> If USB controller disconnected from bus then the gadget driver
>>>> must be notified about the disconnect immediately. The controller
>>>> may or may not be stopped by the core.
>>>>
>>>
>>> Then, would you give some comments when this API will be used?
>>> I was assumed it is only used for drd state machine.
>>
>> drd_state machine didn't even need this API in the first place :).
>> You guys wanted me to separate out start/stop and connect/disconnect for full OTG case.
>> Won't full OTG state machine want to use this API? If not what would it use?
>>
> 
> Oh, I meant only drd and fully otg state machine needs it. I am
> wondering if we need have a new API to do it. Two questions:

OK.
> 
> - Except for vbus interrupt, any chances this API will be used at
> current logic?

I don't think so. But we can't assume caller behaviour for any API.

> - When this API is called but without a coming gadget->stop?
> 
Never for DRD case. But we want to catch wrong users.

cheers,
-roger

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v8 08/14] usb: otg: add OTG/dual-role core
       [not found]     ` <CAL411-qb0dHQrn+AarSApCq6L=toKPRerLKDcx_H+5WDWu_VDg@mail.gmail.com>
@ 2016-05-18 12:59       ` Roger Quadros
  2016-05-20  8:31         ` Roger Quadros
  0 siblings, 1 reply; 62+ messages in thread
From: Roger Quadros @ 2016-05-18 12:59 UTC (permalink / raw)
  To: Peter Chen
  Cc: Peter Chen, balbi, tony, Greg Kroah-Hartman, dan.j.williams,
	mathias.nyman, Joao.Pinto, sergei.shtylyov, jun.li,
	grygorii.strashko, yoshihiro.shimoda.uh, robh, nsekhar, b-liu,
	linux-usb, linux-omap, lkml, devicetree

Hi Peter,

On 18/05/16 10:45, Peter Chen wrote:
> 
> 
> On Mon, May 16, 2016 at 5:00 PM, Roger Quadros <rogerq@ti.com <mailto:rogerq@ti.com>> wrote:
> 
>     On 13/05/16 13:03, Roger Quadros wrote:
>     > It provides APIs for the following tasks
>     >
>     > - Registering an OTG/dual-role capable controller
>     > - Registering Host and Gadget controllers to OTG core
>     > - Providing inputs to and kicking the OTG state machine
>     >
>     > Provide a dual-role device (DRD) state machine.
>     > DRD mode is a reduced functionality OTG mode. In this mode
>     > we don't support SRP, HNP and dynamic role-swap.
>     >
>     > In DRD operation, the controller mode (Host or Peripheral)
>     > is decided based on the ID pin status. Once a cable plug (Type-A
>     > or Type-B) is attached the controller selects the state
>     > and doesn't change till the cable in unplugged and a different
>     > cable type is inserted.
>     >
>     > As we don't need most of the complex OTG states and OTG timers
>     > we implement a lean DRD state machine in usb-otg.c.
>     > The DRD state machine is only interested in 2 hardware inputs
>     > 'id' and 'b_sess_vld'.
>     >
>     > Signed-off-by: Roger Quadros <rogerq@ti.com <mailto:rogerq@ti.com>>
>     > ---
>     >  drivers/usb/common/Makefile  |    2 +-
>     >  drivers/usb/common/usb-otg.c | 1042 ++++++++++++++++++++++++++++++++++++++++++
>     >  drivers/usb/core/Kconfig     |    4 +-
>     >  include/linux/usb/gadget.h   |    2 +
>     >  include/linux/usb/hcd.h      |    1 +
>     >  include/linux/usb/otg-fsm.h  |    7 +
>     >  include/linux/usb/otg.h      |  154 ++++++-
>     >  7 files changed, 1206 insertions(+), 6 deletions(-)
>     >  create mode 100644 drivers/usb/common/usb-otg.c
> 
> 
>     This patch causes the following build issues when CONFIG_USB_GADGET=m, CONFIG_USB=m,
>     CONFIG_USB_COMMON=m and CONFIG_USB_OTG=y
> 
>     ERROR: "usb_otg_register_gadget" [drivers/usb/gadget/udc/udc-core.ko] undefined!
>     ERROR: "usb_otg_unregister_gadget" [drivers/usb/gadget/udc/udc-core.ko] undefined!
>     ERROR: "usb_otg_register_hcd" [drivers/usb/core/usbcore.ko] undefined!
>     ERROR: "usb_otg_unregister_hcd" [drivers/usb/core/usbcore.ko] undefined!
>     ERROR: "otg_statemachine" [drivers/usb/chipidea/ci_hdrc.ko] undefined!
>     scripts/Makefile.modpost:91: recipe for target '__modpost' failed
>     make[1]: *** [__modpost] Error 1
>     Makefile:1141: recipe for target 'modules' failed
>     make: *** [modules] Error 2
>     make: *** Waiting for unfinished jobs....
> 
>     drivers/built-in.o: In function `drd_set_state':
>     usb-otg.c:(.text+0x2b4242): undefined reference to `usb_otg_state_string'
>     drivers/built-in.o: In function `drd_statemachine':
>     (.text+0x2b4b4c): undefined reference to `usb_otg_state_string'
>     Makefile:937: recipe for target 'vmlinux' failed
> 
>     I'll fix it up with the following diff.
> 
>     diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile
>     index dca7856..16a5b55 100644
>     --- a/drivers/usb/Makefile
>     +++ b/drivers/usb/Makefile
>     @@ -59,5 +59,6 @@ obj-$(CONFIG_USB_RENESAS_USBHS)       += renesas_usbhs/
>      obj-$(CONFIG_USB_GADGET)       += gadget/
> 
>      obj-$(CONFIG_USB_COMMON)       += common/
>     +obj-$(CONFIG_USB_OTG)          += common/
> 
>      obj-$(CONFIG_USBIP_CORE)       += usbip/
>     diff --git a/drivers/usb/common/usb-otg.c b/drivers/usb/common/usb-otg.c
>     index 77048aa..17e449e 100644
>     --- a/drivers/usb/common/usb-otg.c
>     +++ b/drivers/usb/common/usb-otg.c
>     @@ -56,6 +56,30 @@ static int usb_otg_hcd_is_primary_hcd(struct usb_hcd *hcd)
>             return hcd == hcd->primary_hcd;
>      }
> 
>     +static const char *otg_state_string(enum usb_otg_state state)
>     +{
>     +       static const char *const names[] = {
>     +               [OTG_STATE_A_IDLE] = "a_idle",
>     +               [OTG_STATE_A_WAIT_VRISE] = "a_wait_vrise",
>     +               [OTG_STATE_A_WAIT_BCON] = "a_wait_bcon",
>     +               [OTG_STATE_A_HOST] = "a_host",
>     +               [OTG_STATE_A_SUSPEND] = "a_suspend",
>     +               [OTG_STATE_A_PERIPHERAL] = "a_peripheral",
>     +               [OTG_STATE_A_WAIT_VFALL] = "a_wait_vfall",
>     +               [OTG_STATE_A_VBUS_ERR] = "a_vbus_err",
>     +               [OTG_STATE_B_IDLE] = "b_idle",
>     +               [OTG_STATE_B_SRP_INIT] = "b_srp_init",
>     +               [OTG_STATE_B_PERIPHERAL] = "b_peripheral",
>     +               [OTG_STATE_B_WAIT_ACON] = "b_wait_acon",
>     +               [OTG_STATE_B_HOST] = "b_host",
>     +       };
>     +
>     +       if (state < 0 || state >= ARRAY_SIZE(names))
>     +               return "UNDEFINED";
>     +
>     +       return names[state];
>     +}
>     +
> 
> 
> 
> From my point, make another copy for otg stuff is not a good way,
> could we make folder under usb/ named otg for dedicated otg stuffs,
> in that case, build otg stuffs can not depend on USB_COMMON.

OK. I can try that. I'll delete otg_state_string from usb-common.c and
move it into usb/otg/usb-otg.c

I'll also move usb-otg-fsm.c to usb/otg/.

cheers,
-roger

> 
> Peter
>  
> 
>      /**
>       * Check if the OTG device is in our wait list and return
>       * otg_wait_data, else NULL.
>     @@ -433,7 +457,7 @@ static void drd_set_state(struct otg_fsm *fsm, enum usb_otg_state new_state)
> 
>             fsm->state_changed = 1;
>             dev_dbg(otg->dev, "otg: set state: %s\n",
>     -               usb_otg_state_string(new_state));
>     +               otg_state_string(new_state));
>             switch (new_state) {
>             case OTG_STATE_B_IDLE:
>                     drd_set_protocol(fsm, PROTO_UNDEF);
>     @@ -449,7 +473,7 @@ static void drd_set_state(struct otg_fsm *fsm, enum usb_otg_state new_state)
>                     break;
>             default:
>                     dev_warn(otg->dev, "%s: otg: invalid state: %s\n",
>     -                        __func__, usb_otg_state_string(new_state));
>     +                        __func__, otg_state_string(new_state));
>                     break;
>             }
> 
>     @@ -507,7 +531,7 @@ int drd_statemachine(struct usb_otg *otg)
> 
>             default:
>                     dev_err(otg->dev, "%s: otg: invalid usb-drd state: %s\n",
>     -                       __func__, usb_otg_state_string(state));
>     +                       __func__, otg_state_string(state));
>                     break;
>             }
> 
>     --
>     cheers,
>     -roger
>     --
>     To unsubscribe from this list: send the line "unsubscribe linux-usb" in
>     the body of a message to majordomo@vger.kernel.org <mailto:majordomo@vger.kernel.org>
>     More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 
> 
> 
> 
> -- 
> BR,
> Peter Chen

^ permalink raw reply	[flat|nested] 62+ messages in thread

* RE: [PATCH v8 13/14] usb: gadget: udc: adapt to OTG core
  2016-05-18 12:42                 ` Roger Quadros
@ 2016-05-18 13:12                   ` Jun Li
  2016-05-18 13:43                     ` Roger Quadros
  0 siblings, 1 reply; 62+ messages in thread
From: Jun Li @ 2016-05-18 13:12 UTC (permalink / raw)
  To: Roger Quadros, Peter Chen
  Cc: peter.chen, balbi, tony, gregkh, dan.j.williams, mathias.nyman,
	Joao.Pinto, sergei.shtylyov, jun.li, grygorii.strashko,
	yoshihiro.shimoda.uh, robh, nsekhar, b-liu, linux-usb,
	linux-omap, linux-kernel, devicetree

Hi

> -----Original Message-----
> From: Roger Quadros [mailto:rogerq@ti.com]
> Sent: Wednesday, May 18, 2016 8:43 PM
> To: Jun Li <jun.li@nxp.com>; Peter Chen <hzpeterchen@gmail.com>
> Cc: peter.chen@freescale.com; balbi@kernel.org; tony@atomide.com;
> gregkh@linuxfoundation.org; dan.j.williams@intel.com;
> mathias.nyman@linux.intel.com; Joao.Pinto@synopsys.com;
> sergei.shtylyov@cogentembedded.com; jun.li@freescale.com;
> grygorii.strashko@ti.com; yoshihiro.shimoda.uh@renesas.com;
> robh@kernel.org; nsekhar@ti.com; b-liu@ti.com; linux-usb@vger.kernel.org;
> linux-omap@vger.kernel.org; linux-kernel@vger.kernel.org;
> devicetree@vger.kernel.org
> Subject: Re: [PATCH v8 13/14] usb: gadget: udc: adapt to OTG core
> 
> On 17/05/16 11:28, Jun Li wrote:
> > Hi Roger,
> >
> >> -----Original Message-----
> >> From: Roger Quadros [mailto:rogerq@ti.com]
> >> Sent: Tuesday, May 17, 2016 4:09 PM
> >> To: Jun Li <jun.li@nxp.com>; Peter Chen <hzpeterchen@gmail.com>
> >> Cc: peter.chen@freescale.com; balbi@kernel.org; tony@atomide.com;
> >> gregkh@linuxfoundation.org; dan.j.williams@intel.com;
> >> mathias.nyman@linux.intel.com; Joao.Pinto@synopsys.com;
> >> sergei.shtylyov@cogentembedded.com; jun.li@freescale.com;
> >> grygorii.strashko@ti.com; yoshihiro.shimoda.uh@renesas.com;
> >> robh@kernel.org; nsekhar@ti.com; b-liu@ti.com;
> >> linux-usb@vger.kernel.org; linux-omap@vger.kernel.org;
> >> linux-kernel@vger.kernel.org; devicetree@vger.kernel.org
> >> Subject: Re: [PATCH v8 13/14] usb: gadget: udc: adapt to OTG core
> >>
> >> On 17/05/16 10:38, Jun Li wrote:
> >>> Hi
> >>>
> >>>> -----Original Message-----
> >>>> From: Roger Quadros [mailto:rogerq@ti.com]
> >>>> Sent: Monday, May 16, 2016 5:52 PM
> >>>> To: Peter Chen <hzpeterchen@gmail.com>
> >>>> Cc: peter.chen@freescale.com; balbi@kernel.org; tony@atomide.com;
> >>>> gregkh@linuxfoundation.org; dan.j.williams@intel.com;
> >>>> mathias.nyman@linux.intel.com; Joao.Pinto@synopsys.com;
> >>>> sergei.shtylyov@cogentembedded.com; jun.li@freescale.com;
> >>>> grygorii.strashko@ti.com; yoshihiro.shimoda.uh@renesas.com;
> >>>> robh@kernel.org; nsekhar@ti.com; b-liu@ti.com;
> >>>> linux-usb@vger.kernel.org; linux-omap@vger.kernel.org;
> >>>> linux-kernel@vger.kernel.org; devicetree@vger.kernel.org
> >>>> Subject: Re: [PATCH v8 13/14] usb: gadget: udc: adapt to OTG core
> >>>>
> >>>> On 16/05/16 12:23, Peter Chen wrote:
> >>>>> On Mon, May 16, 2016 at 11:26:57AM +0300, Roger Quadros wrote:
> >>>>>> Hi,
> >>>>>>
> >>>>>> On 16/05/16 10:02, Peter Chen wrote:
> >>>>>>> On Fri, May 13, 2016 at 01:03:27PM +0300, Roger Quadros wrote:
> >>>>>>>> +
> >>>>>>>> +static int usb_gadget_connect_control(struct usb_gadget
> >>>>>>>> +*gadget, bool connect) {
> >>>>>>>> +	struct usb_udc *udc;
> >>>>>>>> +
> >>>>>>>> +	mutex_lock(&udc_lock);
> >>>>>>>> +	udc = usb_gadget_to_udc(gadget);
> >>>>>>>> +	if (!udc) {
> >>>>>>>> +		dev_err(gadget->dev.parent, "%s: gadget not
> >>>> registered.\n",
> >>>>>>>> +			__func__);
> >>>>>>>> +		mutex_unlock(&udc_lock);
> >>>>>>>> +		return -EINVAL;
> >>>>>>>> +	}
> >>>>>>>> +
> >>>>>>>> +	if (connect) {
> >>>>>>>> +		if (!gadget->connected)
> >>>>>>>> +			usb_gadget_connect(udc->gadget);
> >>>>>>>> +	} else {
> >>>>>>>> +		if (gadget->connected) {
> >>>>>>>> +			usb_gadget_disconnect(udc->gadget);
> >>>>>>>> +			udc->driver->disconnect(udc->gadget);
> >>>>>>>> +		}
> >>>>>>>> +	}
> >>>>>>>> +
> >>>>>>>> +	mutex_unlock(&udc_lock);
> >>>>>>>> +
> >>>>>>>> +	return 0;
> >>>>>>>> +}
> >>>>>>>> +
> >>>>>>>
> >>>>>>> Since this is called for vbus interrupt, why not using
> >>>>>>> usb_udc_vbus_handler directly, and call udc->driver->disconnect
> >>>>>>> at usb_gadget_stop.
> >>>>>>
> >>>>>> We can't assume that this is always called for vbus interrupt so
> >>>>>> I decided not to call usb_udc_vbus_handler.
> >>>>>>
> >>>>>> udc->vbus is really pointless for us. We keep vbus states in our
> >>>>>> state machine and leave udc->vbus as ture always.
> >>>>>>
> >>>>>> Why do you want to move udc->driver->disconnect() to stop?
> >>>>>> If USB controller disconnected from bus then the gadget driver
> >>>>>> must be notified about the disconnect immediately. The controller
> >>>>>> may or may not be stopped by the core.
> >>>>>>
> >>>>>
> >>>>> Then, would you give some comments when this API will be used?
> >>>>> I was assumed it is only used for drd state machine.
> >>>>
> >>>> drd_state machine didn't even need this API in the first place :).
> >>>> You guys wanted me to separate out start/stop and
> >>>> connect/disconnect for full OTG case.
> >>>> Won't full OTG state machine want to use this API? If not what
> >>>> would it use?
> >>>
> >>> Instead create those new interfaces/symbol here and there just aim
> >>> to address build problems in diff configures, Could we only allow
> >>> meaningful combination of those 3 drivers configures?
> >>>
> >>> Hcd=y, gadget=y, otg=y or
> >>> Hcd=m, gadget=m, otg=m
> >>
> >> This is still a limitation.
> >>
> >> It is perfectly fine to have
> >> hcd=m, gadget=y
> >> or
> >> hcd=y, gadget=m
> >
> > I agree it makes sense to have above configs in non-otg case, that is,
> > the 'y' driver can work without 'm' driver loaded.
> >
> > But,
> > in otg enabled(y/m) case, the otherwise config of my list can't make
> > any sense from my point view. That is: some driver is built-in, but it
> > can't work at all if another 'm' driver is not loaded,
> >
> > in another words, the otg driver has to be 'm' if its dependent driver
> > is 'm', correct?
> 
> If both host and gadget are 'm' then otg can be 'm', but if either host or
> gadget is built in then we have no choice but to make otg as built-in.
> 
> I didn't want to have complex Kconfig so decided to have otg as built-in
> only.
> What do you want me to change in existing code? and why?

Remove those stuff which only for pass diff driver config
Like every controller driver need a duplicated

static struct otg_hcd_ops ci_hcd_ops = {
    ...
}

And here is another example, for gadget connect, otg driver can
directly call to usb_udc_vbus_handler() in drd state machine,
but you create another interface:

.connect_control = usb_gadget_connect_control,

If the symbol is defined in one driver which is 'm', another driver
reference it should be 'm' as well, then there is no this kind of problem
as my understanding.

Li Jun 
   
> 
> cheers,
> -roger
> 
> >
> > Li Jun
> >
> >>
> >> cheers,
> >> -roger
> >>
> >>>
> >>> Li Jun
> >>>
> >>>>
> >>>> cheers,
> >>>> -roger
> >>>>
> >>>>>
> >>>>>>>
> >>>>>>>>  	return 0;
> >>>>>>>> @@ -660,9 +830,15 @@ static ssize_t
> >>>>>>>> usb_udc_softconn_store(struct
> >>>> device *dev,
> >>>>>>>>  		return -EOPNOTSUPP;
> >>>>>>>>  	}
> >>>>>>>>
> >>>>>>>> +	/* In OTG mode we don't support softconnect, but b_bus_req */
> >>>>>>>> +	if (udc->gadget->otg_dev) {
> >>>>>>>> +		dev_err(dev, "soft-connect not supported in OTG mode\n");
> >>>>>>>> +		return -EOPNOTSUPP;
> >>>>>>>> +	}
> >>>>>>>> +
> >>>>>>>
> >>>>>>> The soft-connect can be supported at dual-role mode currently,
> >>>>>>> we can use b_bus_req entry once it is implemented later.
> >>>>>>
> >>>>>> Soft-connect should be done via sysfs handling within the OTG core.
> >>>>>> This can be added later. I don't want anything outside the OTG
> >>>>>> core to handle soft-connect behaviour as it will be hard to keep
> >>>>>> things in sync.
> >>>>>>
> >>>>>> I can update the comment to something like this.
> >>>>>>
> >>>>>> /* In OTG/dual-role mode, soft-connect should be handled by OTG
> >>>>>> core */
> >>>>>
> >>>>> Ok, let's Felipe decide it.
> >>>>>
> >>>>>>
> >>>>>>>
> >>>>>>>>  	if (sysfs_streq(buf, "connect")) {
> >>>>>>>>  		usb_gadget_udc_start(udc);
> >>>>>>>> -		usb_gadget_connect(udc->gadget);
> >>>>>>>> +		usb_udc_connect_control(udc);
> >>>>>>>
> >>>>>>> This line seems to be not related with this patch.
> >>>>>>>
> >>>>>> Right. I'll remove it.
> >>>>>>
> >>>>>> cheers,
> >>>>>> -roger
> >>>>>

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v8 13/14] usb: gadget: udc: adapt to OTG core
  2016-05-18 13:12                   ` Jun Li
@ 2016-05-18 13:43                     ` Roger Quadros
  2016-05-18 14:46                       ` Jun Li
  0 siblings, 1 reply; 62+ messages in thread
From: Roger Quadros @ 2016-05-18 13:43 UTC (permalink / raw)
  To: Jun Li, Peter Chen
  Cc: peter.chen, balbi, tony, gregkh, dan.j.williams, mathias.nyman,
	Joao.Pinto, sergei.shtylyov, jun.li, grygorii.strashko,
	yoshihiro.shimoda.uh, robh, nsekhar, b-liu, linux-usb,
	linux-omap, linux-kernel, devicetree

On 18/05/16 16:12, Jun Li wrote:
> Hi
> 
>> -----Original Message-----
>> From: Roger Quadros [mailto:rogerq@ti.com]
>> Sent: Wednesday, May 18, 2016 8:43 PM
>> To: Jun Li <jun.li@nxp.com>; Peter Chen <hzpeterchen@gmail.com>
>> Cc: peter.chen@freescale.com; balbi@kernel.org; tony@atomide.com;
>> gregkh@linuxfoundation.org; dan.j.williams@intel.com;
>> mathias.nyman@linux.intel.com; Joao.Pinto@synopsys.com;
>> sergei.shtylyov@cogentembedded.com; jun.li@freescale.com;
>> grygorii.strashko@ti.com; yoshihiro.shimoda.uh@renesas.com;
>> robh@kernel.org; nsekhar@ti.com; b-liu@ti.com; linux-usb@vger.kernel.org;
>> linux-omap@vger.kernel.org; linux-kernel@vger.kernel.org;
>> devicetree@vger.kernel.org
>> Subject: Re: [PATCH v8 13/14] usb: gadget: udc: adapt to OTG core
>>
>> On 17/05/16 11:28, Jun Li wrote:
>>> Hi Roger,
>>>
>>>> -----Original Message-----
>>>> From: Roger Quadros [mailto:rogerq@ti.com]
>>>> Sent: Tuesday, May 17, 2016 4:09 PM
>>>> To: Jun Li <jun.li@nxp.com>; Peter Chen <hzpeterchen@gmail.com>
>>>> Cc: peter.chen@freescale.com; balbi@kernel.org; tony@atomide.com;
>>>> gregkh@linuxfoundation.org; dan.j.williams@intel.com;
>>>> mathias.nyman@linux.intel.com; Joao.Pinto@synopsys.com;
>>>> sergei.shtylyov@cogentembedded.com; jun.li@freescale.com;
>>>> grygorii.strashko@ti.com; yoshihiro.shimoda.uh@renesas.com;
>>>> robh@kernel.org; nsekhar@ti.com; b-liu@ti.com;
>>>> linux-usb@vger.kernel.org; linux-omap@vger.kernel.org;
>>>> linux-kernel@vger.kernel.org; devicetree@vger.kernel.org
>>>> Subject: Re: [PATCH v8 13/14] usb: gadget: udc: adapt to OTG core
>>>>
>>>> On 17/05/16 10:38, Jun Li wrote:
>>>>> Hi
>>>>>
>>>>>> -----Original Message-----
>>>>>> From: Roger Quadros [mailto:rogerq@ti.com]
>>>>>> Sent: Monday, May 16, 2016 5:52 PM
>>>>>> To: Peter Chen <hzpeterchen@gmail.com>
>>>>>> Cc: peter.chen@freescale.com; balbi@kernel.org; tony@atomide.com;
>>>>>> gregkh@linuxfoundation.org; dan.j.williams@intel.com;
>>>>>> mathias.nyman@linux.intel.com; Joao.Pinto@synopsys.com;
>>>>>> sergei.shtylyov@cogentembedded.com; jun.li@freescale.com;
>>>>>> grygorii.strashko@ti.com; yoshihiro.shimoda.uh@renesas.com;
>>>>>> robh@kernel.org; nsekhar@ti.com; b-liu@ti.com;
>>>>>> linux-usb@vger.kernel.org; linux-omap@vger.kernel.org;
>>>>>> linux-kernel@vger.kernel.org; devicetree@vger.kernel.org
>>>>>> Subject: Re: [PATCH v8 13/14] usb: gadget: udc: adapt to OTG core
>>>>>>
>>>>>> On 16/05/16 12:23, Peter Chen wrote:
>>>>>>> On Mon, May 16, 2016 at 11:26:57AM +0300, Roger Quadros wrote:
>>>>>>>> Hi,
>>>>>>>>
>>>>>>>> On 16/05/16 10:02, Peter Chen wrote:
>>>>>>>>> On Fri, May 13, 2016 at 01:03:27PM +0300, Roger Quadros wrote:
>>>>>>>>>> +
>>>>>>>>>> +static int usb_gadget_connect_control(struct usb_gadget
>>>>>>>>>> +*gadget, bool connect) {
>>>>>>>>>> +	struct usb_udc *udc;
>>>>>>>>>> +
>>>>>>>>>> +	mutex_lock(&udc_lock);
>>>>>>>>>> +	udc = usb_gadget_to_udc(gadget);
>>>>>>>>>> +	if (!udc) {
>>>>>>>>>> +		dev_err(gadget->dev.parent, "%s: gadget not
>>>>>> registered.\n",
>>>>>>>>>> +			__func__);
>>>>>>>>>> +		mutex_unlock(&udc_lock);
>>>>>>>>>> +		return -EINVAL;
>>>>>>>>>> +	}
>>>>>>>>>> +
>>>>>>>>>> +	if (connect) {
>>>>>>>>>> +		if (!gadget->connected)
>>>>>>>>>> +			usb_gadget_connect(udc->gadget);
>>>>>>>>>> +	} else {
>>>>>>>>>> +		if (gadget->connected) {
>>>>>>>>>> +			usb_gadget_disconnect(udc->gadget);
>>>>>>>>>> +			udc->driver->disconnect(udc->gadget);
>>>>>>>>>> +		}
>>>>>>>>>> +	}
>>>>>>>>>> +
>>>>>>>>>> +	mutex_unlock(&udc_lock);
>>>>>>>>>> +
>>>>>>>>>> +	return 0;
>>>>>>>>>> +}
>>>>>>>>>> +
>>>>>>>>>
>>>>>>>>> Since this is called for vbus interrupt, why not using
>>>>>>>>> usb_udc_vbus_handler directly, and call udc->driver->disconnect
>>>>>>>>> at usb_gadget_stop.
>>>>>>>>
>>>>>>>> We can't assume that this is always called for vbus interrupt so
>>>>>>>> I decided not to call usb_udc_vbus_handler.
>>>>>>>>
>>>>>>>> udc->vbus is really pointless for us. We keep vbus states in our
>>>>>>>> state machine and leave udc->vbus as ture always.
>>>>>>>>
>>>>>>>> Why do you want to move udc->driver->disconnect() to stop?
>>>>>>>> If USB controller disconnected from bus then the gadget driver
>>>>>>>> must be notified about the disconnect immediately. The controller
>>>>>>>> may or may not be stopped by the core.
>>>>>>>>
>>>>>>>
>>>>>>> Then, would you give some comments when this API will be used?
>>>>>>> I was assumed it is only used for drd state machine.
>>>>>>
>>>>>> drd_state machine didn't even need this API in the first place :).
>>>>>> You guys wanted me to separate out start/stop and
>>>>>> connect/disconnect for full OTG case.
>>>>>> Won't full OTG state machine want to use this API? If not what
>>>>>> would it use?
>>>>>
>>>>> Instead create those new interfaces/symbol here and there just aim
>>>>> to address build problems in diff configures, Could we only allow
>>>>> meaningful combination of those 3 drivers configures?
>>>>>
>>>>> Hcd=y, gadget=y, otg=y or
>>>>> Hcd=m, gadget=m, otg=m
>>>>
>>>> This is still a limitation.
>>>>
>>>> It is perfectly fine to have
>>>> hcd=m, gadget=y
>>>> or
>>>> hcd=y, gadget=m
>>>
>>> I agree it makes sense to have above configs in non-otg case, that is,
>>> the 'y' driver can work without 'm' driver loaded.
>>>
>>> But,
>>> in otg enabled(y/m) case, the otherwise config of my list can't make
>>> any sense from my point view. That is: some driver is built-in, but it
>>> can't work at all if another 'm' driver is not loaded,
>>>
>>> in another words, the otg driver has to be 'm' if its dependent driver
>>> is 'm', correct?
>>
>> If both host and gadget are 'm' then otg can be 'm', but if either host or
>> gadget is built in then we have no choice but to make otg as built-in.
>>
>> I didn't want to have complex Kconfig so decided to have otg as built-in
>> only.
>> What do you want me to change in existing code? and why?
> 
> Remove those stuff which only for pass diff driver config
> Like every controller driver need a duplicated
> 
> static struct otg_hcd_ops ci_hcd_ops = {
>     ...
> }

This is an exception only. Every controller driver doesn't need to implement
hcd_ops. It is implemented in the hcd core.

> 
> And here is another example, for gadget connect, otg driver can
> directly call to usb_udc_vbus_handler() in drd state machine,
> but you create another interface:
> 
> .connect_control = usb_gadget_connect_control,
> 
> If the symbol is defined in one driver which is 'm', another driver
> reference it should be 'm' as well, then there is no this kind of problem
> as my understanding.

That is fine as long as all are 'm'. but how do you solve the case
when Gadget is built in and host is 'm'? OTG has to be built-in and
you will need an hcd to gadget interface.

Do you have any ideas to solve that case?

cheers,
-roger

>>>>>>
>>>>>>>
>>>>>>>>>
>>>>>>>>>>  	return 0;
>>>>>>>>>> @@ -660,9 +830,15 @@ static ssize_t
>>>>>>>>>> usb_udc_softconn_store(struct
>>>>>> device *dev,
>>>>>>>>>>  		return -EOPNOTSUPP;
>>>>>>>>>>  	}
>>>>>>>>>>
>>>>>>>>>> +	/* In OTG mode we don't support softconnect, but b_bus_req */
>>>>>>>>>> +	if (udc->gadget->otg_dev) {
>>>>>>>>>> +		dev_err(dev, "soft-connect not supported in OTG mode\n");
>>>>>>>>>> +		return -EOPNOTSUPP;
>>>>>>>>>> +	}
>>>>>>>>>> +
>>>>>>>>>
>>>>>>>>> The soft-connect can be supported at dual-role mode currently,
>>>>>>>>> we can use b_bus_req entry once it is implemented later.
>>>>>>>>
>>>>>>>> Soft-connect should be done via sysfs handling within the OTG core.
>>>>>>>> This can be added later. I don't want anything outside the OTG
>>>>>>>> core to handle soft-connect behaviour as it will be hard to keep
>>>>>>>> things in sync.
>>>>>>>>
>>>>>>>> I can update the comment to something like this.
>>>>>>>>
>>>>>>>> /* In OTG/dual-role mode, soft-connect should be handled by OTG
>>>>>>>> core */
>>>>>>>
>>>>>>> Ok, let's Felipe decide it.
>>>>>>>
>>>>>>>>
>>>>>>>>>
>>>>>>>>>>  	if (sysfs_streq(buf, "connect")) {
>>>>>>>>>>  		usb_gadget_udc_start(udc);
>>>>>>>>>> -		usb_gadget_connect(udc->gadget);
>>>>>>>>>> +		usb_udc_connect_control(udc);
>>>>>>>>>
>>>>>>>>> This line seems to be not related with this patch.
>>>>>>>>>
>>>>>>>> Right. I'll remove it.
>>>>>>>>
>>>>>>>> cheers,
>>>>>>>> -roger
>>>>>>>

^ permalink raw reply	[flat|nested] 62+ messages in thread

* RE: [PATCH v8 13/14] usb: gadget: udc: adapt to OTG core
  2016-05-18 13:43                     ` Roger Quadros
@ 2016-05-18 14:46                       ` Jun Li
  2016-05-19  7:32                         ` Roger Quadros
  0 siblings, 1 reply; 62+ messages in thread
From: Jun Li @ 2016-05-18 14:46 UTC (permalink / raw)
  To: Roger Quadros, Peter Chen
  Cc: peter.chen, balbi, tony, gregkh, dan.j.williams, mathias.nyman,
	Joao.Pinto, sergei.shtylyov, jun.li, grygorii.strashko,
	yoshihiro.shimoda.uh, robh, nsekhar, b-liu, linux-usb,
	linux-omap, linux-kernel, devicetree



> >>
> >> I didn't want to have complex Kconfig so decided to have otg as
> >> built-in only.
> >> What do you want me to change in existing code? and why?
> >
> > Remove those stuff which only for pass diff driver config Like every
> > controller driver need a duplicated
> >
> > static struct otg_hcd_ops ci_hcd_ops = {
> >     ...
> > }
> 
> This is an exception only. Every controller driver doesn't need to
> implement hcd_ops. It is implemented in the hcd core.
> 
> >
> > And here is another example, for gadget connect, otg driver can
> > directly call to usb_udc_vbus_handler() in drd state machine, but you
> > create another interface:
> >
> > .connect_control = usb_gadget_connect_control,
> >
> > If the symbol is defined in one driver which is 'm', another driver
> > reference it should be 'm' as well, then there is no this kind of
> > problem as my understanding.
> 
> That is fine as long as all are 'm'. but how do you solve the case when
> Gadget is built in and host is 'm'? OTG has to be built-in and you will
> need an hcd to gadget interface.

Hcd to gadget interface? Or you want to say otg to host interface?

I think hcd and gadget are independent each other, now

Hcd --> otg; and gadget --> otg, (hcd and gadget use otg's symbol)

If you directly call to usb_udc_vbus_handler() in drd state machine

Then:

Hcd --> otg; and gadget <--> otg, (gadget and otg will refer to symbol of each other)

Li Jun

> 
> Do you have any ideas to solve that case?
> 
> cheers,
> -roger
> 
> >>>>>>
> >>>>>>>
> >>>>>>>>>
> >>>>>>>>>>  	return 0;
> >>>>>>>>>> @@ -660,9 +830,15 @@ static ssize_t
> >>>>>>>>>> usb_udc_softconn_store(struct
> >>>>>> device *dev,
> >>>>>>>>>>  		return -EOPNOTSUPP;
> >>>>>>>>>>  	}
> >>>>>>>>>>
> >>>>>>>>>> +	/* In OTG mode we don't support softconnect, but
> b_bus_req */
> >>>>>>>>>> +	if (udc->gadget->otg_dev) {
> >>>>>>>>>> +		dev_err(dev, "soft-connect not supported in OTG
> mode\n");
> >>>>>>>>>> +		return -EOPNOTSUPP;
> >>>>>>>>>> +	}
> >>>>>>>>>> +
> >>>>>>>>>
> >>>>>>>>> The soft-connect can be supported at dual-role mode currently,
> >>>>>>>>> we can use b_bus_req entry once it is implemented later.
> >>>>>>>>
> >>>>>>>> Soft-connect should be done via sysfs handling within the OTG
> core.
> >>>>>>>> This can be added later. I don't want anything outside the OTG
> >>>>>>>> core to handle soft-connect behaviour as it will be hard to
> >>>>>>>> keep things in sync.
> >>>>>>>>
> >>>>>>>> I can update the comment to something like this.
> >>>>>>>>
> >>>>>>>> /* In OTG/dual-role mode, soft-connect should be handled by OTG
> >>>>>>>> core */
> >>>>>>>
> >>>>>>> Ok, let's Felipe decide it.
> >>>>>>>
> >>>>>>>>
> >>>>>>>>>
> >>>>>>>>>>  	if (sysfs_streq(buf, "connect")) {
> >>>>>>>>>>  		usb_gadget_udc_start(udc);
> >>>>>>>>>> -		usb_gadget_connect(udc->gadget);
> >>>>>>>>>> +		usb_udc_connect_control(udc);
> >>>>>>>>>
> >>>>>>>>> This line seems to be not related with this patch.
> >>>>>>>>>
> >>>>>>>> Right. I'll remove it.
> >>>>>>>>
> >>>>>>>> cheers,
> >>>>>>>> -roger
> >>>>>>>

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v8 13/14] usb: gadget: udc: adapt to OTG core
  2016-05-18 14:46                       ` Jun Li
@ 2016-05-19  7:32                         ` Roger Quadros
  2016-05-21  2:29                           ` Peter Chen
  0 siblings, 1 reply; 62+ messages in thread
From: Roger Quadros @ 2016-05-19  7:32 UTC (permalink / raw)
  To: Jun Li, Peter Chen
  Cc: peter.chen, balbi, tony, gregkh, dan.j.williams, mathias.nyman,
	Joao.Pinto, sergei.shtylyov, jun.li, grygorii.strashko,
	yoshihiro.shimoda.uh, robh, nsekhar, b-liu, linux-usb,
	linux-omap, linux-kernel, devicetree

On 18/05/16 17:46, Jun Li wrote:
> 
> 
>>>>
>>>> I didn't want to have complex Kconfig so decided to have otg as
>>>> built-in only.
>>>> What do you want me to change in existing code? and why?
>>>
>>> Remove those stuff which only for pass diff driver config Like every
>>> controller driver need a duplicated
>>>
>>> static struct otg_hcd_ops ci_hcd_ops = {
>>>     ...
>>> }
>>
>> This is an exception only. Every controller driver doesn't need to
>> implement hcd_ops. It is implemented in the hcd core.
>>
>>>
>>> And here is another example, for gadget connect, otg driver can
>>> directly call to usb_udc_vbus_handler() in drd state machine, but you
>>> create another interface:
>>>
>>> .connect_control = usb_gadget_connect_control,
>>>
>>> If the symbol is defined in one driver which is 'm', another driver
>>> reference it should be 'm' as well, then there is no this kind of
>>> problem as my understanding.
>>
>> That is fine as long as all are 'm'. but how do you solve the case when
>> Gadget is built in and host is 'm'? OTG has to be built-in and you will
>> need an hcd to gadget interface.
> 
> Hcd to gadget interface? Or you want to say otg to host interface?

Sorry, I meant to say host to otg interface.

> 
> I think hcd and gadget are independent each other, now
> 
> Hcd --> otg; and gadget --> otg, (hcd and gadget use otg's symbol)

It is actually a circular dependency for both.
 hcd <--> otg and gadget <--> otg

hcd -> otg for usb_otg_register/unregister_hcd
otg -> hcd for usb_add/remove_hcd, usb_bus_start_enum, usb_control_msg, usb_hub_find_child

gadget -> otg for usb_otg_register/unregister_gadget
otg -> gadget for usb_gadget_start/stop, usb_udc_vbus_handler

Now consider what will happen if I get rid of the otg_hcd and otg_gadget interfaces.
'y' means built-in, 'm' means module.

1) hcd 'y', gadget 'y'
otg has to be 'y' for proper build.

2) hcd 'm', gadget 'm'
otg has to be 'm' for proper build.

3) hcd 'y', gadget 'm'
Build will fail always.
If otg is 'y', otg build will fail due to dependency on gadget.
If otg is 'm', hcd build will fail due to dependency on otg.

4) hcd 'm', gadget 'y'
Build will fail always.
If otg is 'y', otg build will fail due to dependency on hcd.
If otg is 'm', gadget build will fails due to dependency on otg.

So I solve this problem by adding the otg_hcd_ops and otg_gadget_ops
to remove otg->hcd and otg->gadget dependency.

Now we can address 3) and 4) like so

3) hcd 'y', gadget 'm'
otg has to be 'y' for proper build.

4) hcd 'm', gadget 'y'
otg has to be 'y' for proper build.

> 
> If you directly call to usb_udc_vbus_handler() in drd state machine
> 
> Then:
> 
> Hcd --> otg; and gadget <--> otg, (gadget and otg will refer to symbol of each other)

It's not so easy. We are again creating a circular dependency and all
build configurations don't work like I pointed above.

The only optimization I could do is make CONFIG_OTG tristate and
allow it to be built as 'm' if both hcd and gadget are 'm'.
i.e. case (2).

cheers,
-roger

>>
>> Do you have any ideas to solve that case?
>>
>> cheers,
>> -roger
>>
>>>>>>>>
>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>>  	return 0;
>>>>>>>>>>>> @@ -660,9 +830,15 @@ static ssize_t
>>>>>>>>>>>> usb_udc_softconn_store(struct
>>>>>>>> device *dev,
>>>>>>>>>>>>  		return -EOPNOTSUPP;
>>>>>>>>>>>>  	}
>>>>>>>>>>>>
>>>>>>>>>>>> +	/* In OTG mode we don't support softconnect, but
>> b_bus_req */
>>>>>>>>>>>> +	if (udc->gadget->otg_dev) {
>>>>>>>>>>>> +		dev_err(dev, "soft-connect not supported in OTG
>> mode\n");
>>>>>>>>>>>> +		return -EOPNOTSUPP;
>>>>>>>>>>>> +	}
>>>>>>>>>>>> +
>>>>>>>>>>>
>>>>>>>>>>> The soft-connect can be supported at dual-role mode currently,
>>>>>>>>>>> we can use b_bus_req entry once it is implemented later.
>>>>>>>>>>
>>>>>>>>>> Soft-connect should be done via sysfs handling within the OTG
>> core.
>>>>>>>>>> This can be added later. I don't want anything outside the OTG
>>>>>>>>>> core to handle soft-connect behaviour as it will be hard to
>>>>>>>>>> keep things in sync.
>>>>>>>>>>
>>>>>>>>>> I can update the comment to something like this.
>>>>>>>>>>
>>>>>>>>>> /* In OTG/dual-role mode, soft-connect should be handled by OTG
>>>>>>>>>> core */
>>>>>>>>>
>>>>>>>>> Ok, let's Felipe decide it.
>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>>  	if (sysfs_streq(buf, "connect")) {
>>>>>>>>>>>>  		usb_gadget_udc_start(udc);
>>>>>>>>>>>> -		usb_gadget_connect(udc->gadget);
>>>>>>>>>>>> +		usb_udc_connect_control(udc);
>>>>>>>>>>>
>>>>>>>>>>> This line seems to be not related with this patch.
>>>>>>>>>>>
>>>>>>>>>> Right. I'll remove it.
>>>>>>>>>>
>>>>>>>>>> cheers,
>>>>>>>>>> -roger
>>>>>>>>>

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v8 13/14] usb: gadget: udc: adapt to OTG core
  2016-05-18 12:45             ` Roger Quadros
@ 2016-05-20  1:39               ` Peter Chen
  2016-05-20  7:26                 ` Roger Quadros
  0 siblings, 1 reply; 62+ messages in thread
From: Peter Chen @ 2016-05-20  1:39 UTC (permalink / raw)
  To: Roger Quadros
  Cc: peter.chen, balbi, tony, gregkh, dan.j.williams, mathias.nyman,
	Joao.Pinto, sergei.shtylyov, jun.li, grygorii.strashko,
	yoshihiro.shimoda.uh, robh, nsekhar, b-liu, linux-usb,
	linux-omap, linux-kernel, devicetree

On Wed, May 18, 2016 at 03:45:11PM +0300, Roger Quadros wrote:
> On 18/05/16 06:18, Peter Chen wrote:
> > On Mon, May 16, 2016 at 12:51:53PM +0300, Roger Quadros wrote:
> >> On 16/05/16 12:23, Peter Chen wrote:
> >>> On Mon, May 16, 2016 at 11:26:57AM +0300, Roger Quadros wrote:
> >>>> Hi,
> >>>>
> >>>> On 16/05/16 10:02, Peter Chen wrote:
> >>>>> On Fri, May 13, 2016 at 01:03:27PM +0300, Roger Quadros wrote:
> >>>>>> +
> >>>>>> +static int usb_gadget_connect_control(struct usb_gadget *gadget, bool connect)
> >>>>>> +{
> >>>>>> +	struct usb_udc *udc;
> >>>>>> +
> >>>>>> +	mutex_lock(&udc_lock);
> >>>>>> +	udc = usb_gadget_to_udc(gadget);
> >>>>>> +	if (!udc) {
> >>>>>> +		dev_err(gadget->dev.parent, "%s: gadget not registered.\n",
> >>>>>> +			__func__);
> >>>>>> +		mutex_unlock(&udc_lock);
> >>>>>> +		return -EINVAL;
> >>>>>> +	}
> >>>>>> +
> >>>>>> +	if (connect) {
> >>>>>> +		if (!gadget->connected)
> >>>>>> +			usb_gadget_connect(udc->gadget);
> >>>>>> +	} else {
> >>>>>> +		if (gadget->connected) {
> >>>>>> +			usb_gadget_disconnect(udc->gadget);
> >>>>>> +			udc->driver->disconnect(udc->gadget);
> >>>>>> +		}
> >>>>>> +	}
> >>>>>> +
> >>>>>> +	mutex_unlock(&udc_lock);
> >>>>>> +
> >>>>>> +	return 0;
> >>>>>> +}
> >>>>>> +
> >>>>>
> >>>>> Since this is called for vbus interrupt, why not using
> >>>>> usb_udc_vbus_handler directly, and call udc->driver->disconnect
> >>>>> at usb_gadget_stop.
> >>>>
> >>>> We can't assume that this is always called for vbus interrupt so
> >>>> I decided not to call usb_udc_vbus_handler.
> >>>>
> >>>> udc->vbus is really pointless for us. We keep vbus states in our
> >>>> state machine and leave udc->vbus as ture always.
> >>>>
> >>>> Why do you want to move udc->driver->disconnect() to stop?
> >>>> If USB controller disconnected from bus then the gadget driver
> >>>> must be notified about the disconnect immediately. The controller
> >>>> may or may not be stopped by the core.
> >>>>
> >>>
> >>> Then, would you give some comments when this API will be used?
> >>> I was assumed it is only used for drd state machine.
> >>
> >> drd_state machine didn't even need this API in the first place :).
> >> You guys wanted me to separate out start/stop and connect/disconnect for full OTG case.
> >> Won't full OTG state machine want to use this API? If not what would it use?
> >>
> > 
> > Oh, I meant only drd and fully otg state machine needs it. I am
> > wondering if we need have a new API to do it. Two questions:
> 
> OK.
> > 
> > - Except for vbus interrupt, any chances this API will be used at
> > current logic?
> 
> I don't think so. But we can't assume caller behaviour for any API.
> 
> > - When this API is called but without a coming gadget->stop?
> > 
> Never for DRD case. But we want to catch wrong users.
> 

In future, otg_start_gadget will be used for both DRD and fully OTG FSM.
There is no otg_loc_conn at current DRD FSM, but there is
otg_loc_conn at current OTG FSM, see below.

DRD FSM:
	case OTG_STATE_B_IDLE:
		drd_set_protocol(fsm, PROTO_UNDEF);
		otg_drv_vbus(otg, 0);
		break;
	case OTG_STATE_B_PERIPHERAL:
		drd_set_protocol(fsm, PROTO_GADGET);
		otg_drv_vbus(otg, 0);
		break;

OTG FSM:
	case OTG_STATE_B_IDLE:
		otg_drv_vbus(otg, 0);
		otg_chrg_vbus(otg, 0);
		otg_loc_conn(otg, 0);
		otg_loc_sof(otg, 0);
		/*
		 * Driver is responsible for starting ADP probing
		 * if ADP sensing times out.
		 */
		otg_start_adp_sns(otg);
		otg_set_protocol(fsm, PROTO_UNDEF);
		otg_add_timer(otg, B_SE0_SRP);
		break;
	case OTG_STATE_B_PERIPHERAL:
		otg_chrg_vbus(otg, 0);
		otg_loc_sof(otg, 0);
		otg_set_protocol(fsm, PROTO_GADGET);
		otg_loc_conn(otg, 1);
		break;

My original suggestion is to have an API to do pull dp and this API
will be used at both DRD and OTG FSM, and called at otg_loc_conn.
The (de)initialize is the same for both two FSMs, it both includes
init peripheral mode and pull up dp, and can be done by drd_set_protocol(fsm, PROTO_GADGET)
otg_loc_conn(otg, 1);

What do you think?

-- 

Best Regards,
Peter Chen

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v8 13/14] usb: gadget: udc: adapt to OTG core
  2016-05-20  1:39               ` Peter Chen
@ 2016-05-20  7:26                 ` Roger Quadros
  2016-05-21  2:44                   ` Peter Chen
  0 siblings, 1 reply; 62+ messages in thread
From: Roger Quadros @ 2016-05-20  7:26 UTC (permalink / raw)
  To: Peter Chen
  Cc: peter.chen, balbi, tony, gregkh, dan.j.williams, mathias.nyman,
	Joao.Pinto, sergei.shtylyov, jun.li, grygorii.strashko,
	yoshihiro.shimoda.uh, robh, nsekhar, b-liu, linux-usb,
	linux-omap, linux-kernel, devicetree

Peter,

On 20/05/16 04:39, Peter Chen wrote:
> On Wed, May 18, 2016 at 03:45:11PM +0300, Roger Quadros wrote:
>> On 18/05/16 06:18, Peter Chen wrote:
>>> On Mon, May 16, 2016 at 12:51:53PM +0300, Roger Quadros wrote:
>>>> On 16/05/16 12:23, Peter Chen wrote:
>>>>> On Mon, May 16, 2016 at 11:26:57AM +0300, Roger Quadros wrote:
>>>>>> Hi,
>>>>>>
>>>>>> On 16/05/16 10:02, Peter Chen wrote:
>>>>>>> On Fri, May 13, 2016 at 01:03:27PM +0300, Roger Quadros wrote:
>>>>>>>> +
>>>>>>>> +static int usb_gadget_connect_control(struct usb_gadget *gadget, bool connect)
>>>>>>>> +{
>>>>>>>> +	struct usb_udc *udc;
>>>>>>>> +
>>>>>>>> +	mutex_lock(&udc_lock);
>>>>>>>> +	udc = usb_gadget_to_udc(gadget);
>>>>>>>> +	if (!udc) {
>>>>>>>> +		dev_err(gadget->dev.parent, "%s: gadget not registered.\n",
>>>>>>>> +			__func__);
>>>>>>>> +		mutex_unlock(&udc_lock);
>>>>>>>> +		return -EINVAL;
>>>>>>>> +	}
>>>>>>>> +
>>>>>>>> +	if (connect) {
>>>>>>>> +		if (!gadget->connected)
>>>>>>>> +			usb_gadget_connect(udc->gadget);
>>>>>>>> +	} else {
>>>>>>>> +		if (gadget->connected) {
>>>>>>>> +			usb_gadget_disconnect(udc->gadget);
>>>>>>>> +			udc->driver->disconnect(udc->gadget);
>>>>>>>> +		}
>>>>>>>> +	}
>>>>>>>> +
>>>>>>>> +	mutex_unlock(&udc_lock);
>>>>>>>> +
>>>>>>>> +	return 0;
>>>>>>>> +}
>>>>>>>> +
>>>>>>>
>>>>>>> Since this is called for vbus interrupt, why not using
>>>>>>> usb_udc_vbus_handler directly, and call udc->driver->disconnect
>>>>>>> at usb_gadget_stop.
>>>>>>
>>>>>> We can't assume that this is always called for vbus interrupt so
>>>>>> I decided not to call usb_udc_vbus_handler.
>>>>>>
>>>>>> udc->vbus is really pointless for us. We keep vbus states in our
>>>>>> state machine and leave udc->vbus as ture always.
>>>>>>
>>>>>> Why do you want to move udc->driver->disconnect() to stop?
>>>>>> If USB controller disconnected from bus then the gadget driver
>>>>>> must be notified about the disconnect immediately. The controller
>>>>>> may or may not be stopped by the core.
>>>>>>
>>>>>
>>>>> Then, would you give some comments when this API will be used?
>>>>> I was assumed it is only used for drd state machine.
>>>>
>>>> drd_state machine didn't even need this API in the first place :).
>>>> You guys wanted me to separate out start/stop and connect/disconnect for full OTG case.
>>>> Won't full OTG state machine want to use this API? If not what would it use?
>>>>
>>>
>>> Oh, I meant only drd and fully otg state machine needs it. I am
>>> wondering if we need have a new API to do it. Two questions:
>>
>> OK.
>>>
>>> - Except for vbus interrupt, any chances this API will be used at
>>> current logic?
>>
>> I don't think so. But we can't assume caller behaviour for any API.
>>
>>> - When this API is called but without a coming gadget->stop?
>>>
>> Never for DRD case. But we want to catch wrong users.
>>
> 
> In future, otg_start_gadget will be used for both DRD and fully OTG FSM.
> There is no otg_loc_conn at current DRD FSM, but there is
> otg_loc_conn at current OTG FSM, see below.
> 
> DRD FSM:
> 	case OTG_STATE_B_IDLE:
> 		drd_set_protocol(fsm, PROTO_UNDEF);
> 		otg_drv_vbus(otg, 0);
> 		break;
> 	case OTG_STATE_B_PERIPHERAL:
> 		drd_set_protocol(fsm, PROTO_GADGET);
> 		otg_drv_vbus(otg, 0);
> 		break;
> 
> OTG FSM:
> 	case OTG_STATE_B_IDLE:
> 		otg_drv_vbus(otg, 0);
> 		otg_chrg_vbus(otg, 0);
> 		otg_loc_conn(otg, 0);
> 		otg_loc_sof(otg, 0);
> 		/*
> 		 * Driver is responsible for starting ADP probing
> 		 * if ADP sensing times out.
> 		 */
> 		otg_start_adp_sns(otg);
> 		otg_set_protocol(fsm, PROTO_UNDEF);
> 		otg_add_timer(otg, B_SE0_SRP);
> 		break;
> 	case OTG_STATE_B_PERIPHERAL:
> 		otg_chrg_vbus(otg, 0);
> 		otg_loc_sof(otg, 0);
> 		otg_set_protocol(fsm, PROTO_GADGET);
> 		otg_loc_conn(otg, 1);
> 		break;
> 
> My original suggestion is to have an API to do pull dp and this API
> will be used at both DRD and OTG FSM, and called at otg_loc_conn.

The API is usb_gadget_connect_control();

> The (de)initialize is the same for both two FSMs, it both includes
> init peripheral mode and pull up dp, and can be done by drd_set_protocol(fsm, PROTO_GADGET)
> otg_loc_conn(otg, 1);
> 
> What do you think?
> 

I think loc_conn is a bit confusing to drd users. Another issue I see is that 
DRD controller drivers will need to explicitly pass .loc_conn ops via the otg_fsm_ops.
This is an additional step and totally unnecessary as it can be automatically done
via direct DRD -> UDC-core call.

cheers,
-roger

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v8 08/14] usb: otg: add OTG/dual-role core
  2016-05-18 12:59       ` Roger Quadros
@ 2016-05-20  8:31         ` Roger Quadros
  2016-05-20  9:19           ` Roger Quadros
  0 siblings, 1 reply; 62+ messages in thread
From: Roger Quadros @ 2016-05-20  8:31 UTC (permalink / raw)
  To: Peter Chen
  Cc: Peter Chen, balbi, tony, Greg Kroah-Hartman, dan.j.williams,
	mathias.nyman, Joao.Pinto, sergei.shtylyov, jun.li,
	grygorii.strashko, yoshihiro.shimoda.uh, robh, nsekhar, b-liu,
	linux-usb, linux-omap, lkml, devicetree

On 18/05/16 15:59, Roger Quadros wrote:
> Hi Peter,
> 
> On 18/05/16 10:45, Peter Chen wrote:
>>
>>
>> On Mon, May 16, 2016 at 5:00 PM, Roger Quadros <rogerq@ti.com <mailto:rogerq@ti.com>> wrote:
>>
>>     On 13/05/16 13:03, Roger Quadros wrote:
>>     > It provides APIs for the following tasks
>>     >
>>     > - Registering an OTG/dual-role capable controller
>>     > - Registering Host and Gadget controllers to OTG core
>>     > - Providing inputs to and kicking the OTG state machine
>>     >
>>     > Provide a dual-role device (DRD) state machine.
>>     > DRD mode is a reduced functionality OTG mode. In this mode
>>     > we don't support SRP, HNP and dynamic role-swap.
>>     >
>>     > In DRD operation, the controller mode (Host or Peripheral)
>>     > is decided based on the ID pin status. Once a cable plug (Type-A
>>     > or Type-B) is attached the controller selects the state
>>     > and doesn't change till the cable in unplugged and a different
>>     > cable type is inserted.
>>     >
>>     > As we don't need most of the complex OTG states and OTG timers
>>     > we implement a lean DRD state machine in usb-otg.c.
>>     > The DRD state machine is only interested in 2 hardware inputs
>>     > 'id' and 'b_sess_vld'.
>>     >
>>     > Signed-off-by: Roger Quadros <rogerq@ti.com <mailto:rogerq@ti.com>>
>>     > ---
>>     >  drivers/usb/common/Makefile  |    2 +-
>>     >  drivers/usb/common/usb-otg.c | 1042 ++++++++++++++++++++++++++++++++++++++++++
>>     >  drivers/usb/core/Kconfig     |    4 +-
>>     >  include/linux/usb/gadget.h   |    2 +
>>     >  include/linux/usb/hcd.h      |    1 +
>>     >  include/linux/usb/otg-fsm.h  |    7 +
>>     >  include/linux/usb/otg.h      |  154 ++++++-
>>     >  7 files changed, 1206 insertions(+), 6 deletions(-)
>>     >  create mode 100644 drivers/usb/common/usb-otg.c
>>
>>
>>     This patch causes the following build issues when CONFIG_USB_GADGET=m, CONFIG_USB=m,
>>     CONFIG_USB_COMMON=m and CONFIG_USB_OTG=y
>>
>>     ERROR: "usb_otg_register_gadget" [drivers/usb/gadget/udc/udc-core.ko] undefined!
>>     ERROR: "usb_otg_unregister_gadget" [drivers/usb/gadget/udc/udc-core.ko] undefined!
>>     ERROR: "usb_otg_register_hcd" [drivers/usb/core/usbcore.ko] undefined!
>>     ERROR: "usb_otg_unregister_hcd" [drivers/usb/core/usbcore.ko] undefined!
>>     ERROR: "otg_statemachine" [drivers/usb/chipidea/ci_hdrc.ko] undefined!
>>     scripts/Makefile.modpost:91: recipe for target '__modpost' failed
>>     make[1]: *** [__modpost] Error 1
>>     Makefile:1141: recipe for target 'modules' failed
>>     make: *** [modules] Error 2
>>     make: *** Waiting for unfinished jobs....
>>
>>     drivers/built-in.o: In function `drd_set_state':
>>     usb-otg.c:(.text+0x2b4242): undefined reference to `usb_otg_state_string'
>>     drivers/built-in.o: In function `drd_statemachine':
>>     (.text+0x2b4b4c): undefined reference to `usb_otg_state_string'
>>     Makefile:937: recipe for target 'vmlinux' failed
>>
>>     I'll fix it up with the following diff.
>>
>>     diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile
>>     index dca7856..16a5b55 100644
>>     --- a/drivers/usb/Makefile
>>     +++ b/drivers/usb/Makefile
>>     @@ -59,5 +59,6 @@ obj-$(CONFIG_USB_RENESAS_USBHS)       += renesas_usbhs/
>>      obj-$(CONFIG_USB_GADGET)       += gadget/
>>
>>      obj-$(CONFIG_USB_COMMON)       += common/
>>     +obj-$(CONFIG_USB_OTG)          += common/
>>
>>      obj-$(CONFIG_USBIP_CORE)       += usbip/
>>     diff --git a/drivers/usb/common/usb-otg.c b/drivers/usb/common/usb-otg.c
>>     index 77048aa..17e449e 100644
>>     --- a/drivers/usb/common/usb-otg.c
>>     +++ b/drivers/usb/common/usb-otg.c
>>     @@ -56,6 +56,30 @@ static int usb_otg_hcd_is_primary_hcd(struct usb_hcd *hcd)
>>             return hcd == hcd->primary_hcd;
>>      }
>>
>>     +static const char *otg_state_string(enum usb_otg_state state)
>>     +{
>>     +       static const char *const names[] = {
>>     +               [OTG_STATE_A_IDLE] = "a_idle",
>>     +               [OTG_STATE_A_WAIT_VRISE] = "a_wait_vrise",
>>     +               [OTG_STATE_A_WAIT_BCON] = "a_wait_bcon",
>>     +               [OTG_STATE_A_HOST] = "a_host",
>>     +               [OTG_STATE_A_SUSPEND] = "a_suspend",
>>     +               [OTG_STATE_A_PERIPHERAL] = "a_peripheral",
>>     +               [OTG_STATE_A_WAIT_VFALL] = "a_wait_vfall",
>>     +               [OTG_STATE_A_VBUS_ERR] = "a_vbus_err",
>>     +               [OTG_STATE_B_IDLE] = "b_idle",
>>     +               [OTG_STATE_B_SRP_INIT] = "b_srp_init",
>>     +               [OTG_STATE_B_PERIPHERAL] = "b_peripheral",
>>     +               [OTG_STATE_B_WAIT_ACON] = "b_wait_acon",
>>     +               [OTG_STATE_B_HOST] = "b_host",
>>     +       };
>>     +
>>     +       if (state < 0 || state >= ARRAY_SIZE(names))
>>     +               return "UNDEFINED";
>>     +
>>     +       return names[state];
>>     +}
>>     +
>>
>>
>>
>> From my point, make another copy for otg stuff is not a good way,
>> could we make folder under usb/ named otg for dedicated otg stuffs,
>> in that case, build otg stuffs can not depend on USB_COMMON.
> 
> OK. I can try that. I'll delete otg_state_string from usb-common.c and
> move it into usb/otg/usb-otg.c
> 
> I'll also move usb-otg-fsm.c to usb/otg/.

But we can't delete usb_otg_state_string() from usb-common.c. That is used at a
number of places whether OTG is enabled or not. 

One option is to make usb-common built in when otg is enabled. What do you say?

cheers,
-roger

>>      /**
>>       * Check if the OTG device is in our wait list and return
>>       * otg_wait_data, else NULL.
>>     @@ -433,7 +457,7 @@ static void drd_set_state(struct otg_fsm *fsm, enum usb_otg_state new_state)
>>
>>             fsm->state_changed = 1;
>>             dev_dbg(otg->dev, "otg: set state: %s\n",
>>     -               usb_otg_state_string(new_state));
>>     +               otg_state_string(new_state));
>>             switch (new_state) {
>>             case OTG_STATE_B_IDLE:
>>                     drd_set_protocol(fsm, PROTO_UNDEF);
>>     @@ -449,7 +473,7 @@ static void drd_set_state(struct otg_fsm *fsm, enum usb_otg_state new_state)
>>                     break;
>>             default:
>>                     dev_warn(otg->dev, "%s: otg: invalid state: %s\n",
>>     -                        __func__, usb_otg_state_string(new_state));
>>     +                        __func__, otg_state_string(new_state));
>>                     break;
>>             }
>>
>>     @@ -507,7 +531,7 @@ int drd_statemachine(struct usb_otg *otg)
>>
>>             default:
>>                     dev_err(otg->dev, "%s: otg: invalid usb-drd state: %s\n",
>>     -                       __func__, usb_otg_state_string(state));
>>     +                       __func__, otg_state_string(state));
>>                     break;
>>             }
>>
>>     --
>>     cheers,
>>     -roger
>>     --
>>     To unsubscribe from this list: send the line "unsubscribe linux-usb" in
>>     the body of a message to majordomo@vger.kernel.org <mailto:majordomo@vger.kernel.org>
>>     More majordomo info at  http://vger.kernel.org/majordomo-info.html
>>
>>
>>
>>
>> -- 
>> BR,
>> Peter Chen
> --
> To unsubscribe from this list: send the line "unsubscribe linux-omap" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v8 08/14] usb: otg: add OTG/dual-role core
  2016-05-20  8:31         ` Roger Quadros
@ 2016-05-20  9:19           ` Roger Quadros
  2016-05-20  9:53             ` Peter Chen
  0 siblings, 1 reply; 62+ messages in thread
From: Roger Quadros @ 2016-05-20  9:19 UTC (permalink / raw)
  To: Peter Chen
  Cc: Peter Chen, balbi, tony, Greg Kroah-Hartman, dan.j.williams,
	mathias.nyman, Joao.Pinto, sergei.shtylyov, jun.li,
	grygorii.strashko, yoshihiro.shimoda.uh, robh, nsekhar, b-liu,
	linux-usb, linux-omap, lkml, devicetree

On 20/05/16 11:31, Roger Quadros wrote:
> On 18/05/16 15:59, Roger Quadros wrote:
>> Hi Peter,
>>
>> On 18/05/16 10:45, Peter Chen wrote:
>>>
>>>
>>> On Mon, May 16, 2016 at 5:00 PM, Roger Quadros <rogerq@ti.com <mailto:rogerq@ti.com>> wrote:
>>>
>>>     On 13/05/16 13:03, Roger Quadros wrote:
>>>     > It provides APIs for the following tasks
>>>     >
>>>     > - Registering an OTG/dual-role capable controller
>>>     > - Registering Host and Gadget controllers to OTG core
>>>     > - Providing inputs to and kicking the OTG state machine
>>>     >
>>>     > Provide a dual-role device (DRD) state machine.
>>>     > DRD mode is a reduced functionality OTG mode. In this mode
>>>     > we don't support SRP, HNP and dynamic role-swap.
>>>     >
>>>     > In DRD operation, the controller mode (Host or Peripheral)
>>>     > is decided based on the ID pin status. Once a cable plug (Type-A
>>>     > or Type-B) is attached the controller selects the state
>>>     > and doesn't change till the cable in unplugged and a different
>>>     > cable type is inserted.
>>>     >
>>>     > As we don't need most of the complex OTG states and OTG timers
>>>     > we implement a lean DRD state machine in usb-otg.c.
>>>     > The DRD state machine is only interested in 2 hardware inputs
>>>     > 'id' and 'b_sess_vld'.
>>>     >
>>>     > Signed-off-by: Roger Quadros <rogerq@ti.com <mailto:rogerq@ti.com>>
>>>     > ---
>>>     >  drivers/usb/common/Makefile  |    2 +-
>>>     >  drivers/usb/common/usb-otg.c | 1042 ++++++++++++++++++++++++++++++++++++++++++
>>>     >  drivers/usb/core/Kconfig     |    4 +-
>>>     >  include/linux/usb/gadget.h   |    2 +
>>>     >  include/linux/usb/hcd.h      |    1 +
>>>     >  include/linux/usb/otg-fsm.h  |    7 +
>>>     >  include/linux/usb/otg.h      |  154 ++++++-
>>>     >  7 files changed, 1206 insertions(+), 6 deletions(-)
>>>     >  create mode 100644 drivers/usb/common/usb-otg.c
>>>
>>>
>>>     This patch causes the following build issues when CONFIG_USB_GADGET=m, CONFIG_USB=m,
>>>     CONFIG_USB_COMMON=m and CONFIG_USB_OTG=y
>>>
>>>     ERROR: "usb_otg_register_gadget" [drivers/usb/gadget/udc/udc-core.ko] undefined!
>>>     ERROR: "usb_otg_unregister_gadget" [drivers/usb/gadget/udc/udc-core.ko] undefined!
>>>     ERROR: "usb_otg_register_hcd" [drivers/usb/core/usbcore.ko] undefined!
>>>     ERROR: "usb_otg_unregister_hcd" [drivers/usb/core/usbcore.ko] undefined!
>>>     ERROR: "otg_statemachine" [drivers/usb/chipidea/ci_hdrc.ko] undefined!
>>>     scripts/Makefile.modpost:91: recipe for target '__modpost' failed
>>>     make[1]: *** [__modpost] Error 1
>>>     Makefile:1141: recipe for target 'modules' failed
>>>     make: *** [modules] Error 2
>>>     make: *** Waiting for unfinished jobs....
>>>
>>>     drivers/built-in.o: In function `drd_set_state':
>>>     usb-otg.c:(.text+0x2b4242): undefined reference to `usb_otg_state_string'
>>>     drivers/built-in.o: In function `drd_statemachine':
>>>     (.text+0x2b4b4c): undefined reference to `usb_otg_state_string'
>>>     Makefile:937: recipe for target 'vmlinux' failed
>>>
>>>     I'll fix it up with the following diff.
>>>
>>>     diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile
>>>     index dca7856..16a5b55 100644
>>>     --- a/drivers/usb/Makefile
>>>     +++ b/drivers/usb/Makefile
>>>     @@ -59,5 +59,6 @@ obj-$(CONFIG_USB_RENESAS_USBHS)       += renesas_usbhs/
>>>      obj-$(CONFIG_USB_GADGET)       += gadget/
>>>
>>>      obj-$(CONFIG_USB_COMMON)       += common/
>>>     +obj-$(CONFIG_USB_OTG)          += common/
>>>
>>>      obj-$(CONFIG_USBIP_CORE)       += usbip/
>>>     diff --git a/drivers/usb/common/usb-otg.c b/drivers/usb/common/usb-otg.c
>>>     index 77048aa..17e449e 100644
>>>     --- a/drivers/usb/common/usb-otg.c
>>>     +++ b/drivers/usb/common/usb-otg.c
>>>     @@ -56,6 +56,30 @@ static int usb_otg_hcd_is_primary_hcd(struct usb_hcd *hcd)
>>>             return hcd == hcd->primary_hcd;
>>>      }
>>>
>>>     +static const char *otg_state_string(enum usb_otg_state state)
>>>     +{
>>>     +       static const char *const names[] = {
>>>     +               [OTG_STATE_A_IDLE] = "a_idle",
>>>     +               [OTG_STATE_A_WAIT_VRISE] = "a_wait_vrise",
>>>     +               [OTG_STATE_A_WAIT_BCON] = "a_wait_bcon",
>>>     +               [OTG_STATE_A_HOST] = "a_host",
>>>     +               [OTG_STATE_A_SUSPEND] = "a_suspend",
>>>     +               [OTG_STATE_A_PERIPHERAL] = "a_peripheral",
>>>     +               [OTG_STATE_A_WAIT_VFALL] = "a_wait_vfall",
>>>     +               [OTG_STATE_A_VBUS_ERR] = "a_vbus_err",
>>>     +               [OTG_STATE_B_IDLE] = "b_idle",
>>>     +               [OTG_STATE_B_SRP_INIT] = "b_srp_init",
>>>     +               [OTG_STATE_B_PERIPHERAL] = "b_peripheral",
>>>     +               [OTG_STATE_B_WAIT_ACON] = "b_wait_acon",
>>>     +               [OTG_STATE_B_HOST] = "b_host",
>>>     +       };
>>>     +
>>>     +       if (state < 0 || state >= ARRAY_SIZE(names))
>>>     +               return "UNDEFINED";
>>>     +
>>>     +       return names[state];
>>>     +}
>>>     +
>>>
>>>
>>>
>>> From my point, make another copy for otg stuff is not a good way,
>>> could we make folder under usb/ named otg for dedicated otg stuffs,
>>> in that case, build otg stuffs can not depend on USB_COMMON.
>>
>> OK. I can try that. I'll delete otg_state_string from usb-common.c and
>> move it into usb/otg/usb-otg.c
>>
>> I'll also move usb-otg-fsm.c to usb/otg/.
> 
> But we can't delete usb_otg_state_string() from usb-common.c. That is used at a
> number of places whether OTG is enabled or not. 
> 
> One option is to make usb-common built in when otg is enabled. What do you say?
> 

This should also get solved if we make USB_OTG tristate so that it is same as
USB_COMMON.

However I haven't had success in making Kconfig behave like this.

USB_OTG = y if USB == y && GADGET = m
USB_OTG = y if USB == m && GADGET = y

Is there any Kconfig trickery to get this behaviour?

cheers,
-roger

> cheers,
> -roger
> 
>>>      /**
>>>       * Check if the OTG device is in our wait list and return
>>>       * otg_wait_data, else NULL.
>>>     @@ -433,7 +457,7 @@ static void drd_set_state(struct otg_fsm *fsm, enum usb_otg_state new_state)
>>>
>>>             fsm->state_changed = 1;
>>>             dev_dbg(otg->dev, "otg: set state: %s\n",
>>>     -               usb_otg_state_string(new_state));
>>>     +               otg_state_string(new_state));
>>>             switch (new_state) {
>>>             case OTG_STATE_B_IDLE:
>>>                     drd_set_protocol(fsm, PROTO_UNDEF);
>>>     @@ -449,7 +473,7 @@ static void drd_set_state(struct otg_fsm *fsm, enum usb_otg_state new_state)
>>>                     break;
>>>             default:
>>>                     dev_warn(otg->dev, "%s: otg: invalid state: %s\n",
>>>     -                        __func__, usb_otg_state_string(new_state));
>>>     +                        __func__, otg_state_string(new_state));
>>>                     break;
>>>             }
>>>
>>>     @@ -507,7 +531,7 @@ int drd_statemachine(struct usb_otg *otg)
>>>
>>>             default:
>>>                     dev_err(otg->dev, "%s: otg: invalid usb-drd state: %s\n",
>>>     -                       __func__, usb_otg_state_string(state));
>>>     +                       __func__, otg_state_string(state));
>>>                     break;
>>>             }
>>>
>>>     --
>>>     cheers,
>>>     -roger
>>>     --
>>>     To unsubscribe from this list: send the line "unsubscribe linux-usb" in
>>>     the body of a message to majordomo@vger.kernel.org <mailto:majordomo@vger.kernel.org>
>>>     More majordomo info at  http://vger.kernel.org/majordomo-info.html
>>>
>>>
>>>
>>>
>>> -- 
>>> BR,
>>> Peter Chen
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-omap" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-usb" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [PATCH v9 09/14] usb: of: add an API to get OTG device from USB controller node
  2016-05-13 10:03 ` [PATCH v8 09/14] usb: of: add an API to get OTG device from USB controller node Roger Quadros
@ 2016-05-20  9:29   ` Roger Quadros
  2016-05-23 21:06     ` Rob Herring
  0 siblings, 1 reply; 62+ messages in thread
From: Roger Quadros @ 2016-05-20  9:29 UTC (permalink / raw)
  To: peter.chen, robh
  Cc: balbi, tony, gregkh, dan.j.williams, mathias.nyman, Joao.Pinto,
	sergei.shtylyov, jun.li, grygorii.strashko, yoshihiro.shimoda.uh,
	nsekhar, b-liu, linux-usb, linux-omap, linux-kernel, devicetree

The OTG controller and the USB controller can be linked via the
'otg-controller' property in the USB controller's device node.

of_usb_get_otg() can be used to get the OTG controller device
from the USB controller's device node.

Signed-off-by: Roger Quadros <rogerq@ti.com>
Acked-by: Peter Chen <peter.chen@nxp.com>
---
v9:
Clearly indicate which properties are for OTG controller and which ones
are for host/device controllers

 Documentation/devicetree/bindings/usb/generic.txt |  7 ++++++
 drivers/usb/common/common.c                       | 27 +++++++++++++++++++++++
 include/linux/usb/of.h                            |  9 ++++++++
 3 files changed, 43 insertions(+)

diff --git a/Documentation/devicetree/bindings/usb/generic.txt b/Documentation/devicetree/bindings/usb/generic.txt
index bba8257..0887d6e 100644
--- a/Documentation/devicetree/bindings/usb/generic.txt
+++ b/Documentation/devicetree/bindings/usb/generic.txt
@@ -11,6 +11,8 @@ Optional properties:
 			"peripheral" and "otg". In case this attribute isn't
 			passed via DT, USB DRD controllers should default to
 			OTG.
+
+Optional properties for OTG controllers:
  - otg-rev: tells usb driver the release number of the OTG and EH supplement
 			with which the device and its descriptors are compliant,
 			in binary-coded decimal (i.e. 2.0 is 0200H). This
@@ -25,6 +27,11 @@ Optional properties:
  - adp-disable: tells OTG controllers we want to disable OTG ADP, ADP is
 			optional for OTG device.
 
+Optional properties for host/device controllers:
+ - otg-controller: phandle to otg controller. Host or gadget controllers can
+			contain this property to link it to a particular OTG
+			controller.
+
 This is an attribute to a USB controller such as:
 
 dwc3@4a030000 {
diff --git a/drivers/usb/common/common.c b/drivers/usb/common/common.c
index e3d0161..d7ec471 100644
--- a/drivers/usb/common/common.c
+++ b/drivers/usb/common/common.c
@@ -238,6 +238,33 @@ int of_usb_update_otg_caps(struct device_node *np,
 }
 EXPORT_SYMBOL_GPL(of_usb_update_otg_caps);
 
+#ifdef CONFIG_USB_OTG
+/**
+ * of_usb_get_otg - get the OTG controller linked to the USB controller
+ * @np: Pointer to the device_node of the USB controller
+ * @otg_caps: Pointer to the target usb_otg_caps to be set
+ *
+ * Returns the OTG controller device or NULL on error.
+ */
+struct device *of_usb_get_otg(struct device_node *np)
+{
+	struct device_node *otg_np;
+	struct platform_device *pdev;
+
+	otg_np = of_parse_phandle(np, "otg-controller", 0);
+	if (!otg_np)
+		return NULL;
+
+	pdev = of_find_device_by_node(otg_np);
+	of_node_put(otg_np);
+	if (!pdev)
+		return NULL;
+
+	return &pdev->dev;
+}
+EXPORT_SYMBOL_GPL(of_usb_get_otg);
+#endif
+
 #endif
 
 MODULE_LICENSE("GPL");
diff --git a/include/linux/usb/of.h b/include/linux/usb/of.h
index de3237f..499a4e8 100644
--- a/include/linux/usb/of.h
+++ b/include/linux/usb/of.h
@@ -40,6 +40,15 @@ static inline struct device_node *usb_of_get_child_node
 }
 #endif
 
+#if IS_ENABLED(CONFIG_OF) && IS_ENABLED(CONFIG_USB_OTG)
+struct device *of_usb_get_otg(struct device_node *np);
+#else
+static inline struct device *of_usb_get_otg(struct device_node *np)
+{
+	return NULL;
+}
+#endif
+
 #if IS_ENABLED(CONFIG_OF) && IS_ENABLED(CONFIG_USB_SUPPORT)
 enum usb_phy_interface of_usb_get_phy_mode(struct device_node *np);
 #else
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH v9 10/14] usb: otg: add hcd companion support
  2016-05-13 10:03 ` [PATCH v8 10/14] usb: otg: add hcd companion support Roger Quadros
  2016-05-13 18:13   ` Rob Herring
@ 2016-05-20  9:32   ` Roger Quadros
  2016-05-23 21:07     ` Rob Herring
  1 sibling, 1 reply; 62+ messages in thread
From: Roger Quadros @ 2016-05-20  9:32 UTC (permalink / raw)
  To: peter.chen, robh
  Cc: balbi, tony, gregkh, dan.j.williams, mathias.nyman, Joao.Pinto,
	sergei.shtylyov, jun.li, grygorii.strashko, yoshihiro.shimoda.uh,
	nsekhar, b-liu, linux-usb, linux-omap, linux-kernel, devicetree,
	rogerq

Since some host controller (e.g. EHCI) needs a companion host controller
(e.g. OHCI), this patch adds such a configuration to use it in the OTG
core.

Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
Signed-off-by: Roger Quadros <rogerq@ti.com>
Acked-by: Peter Chen <peter.chen@nxp.com>
---
v9:
- add DT property documentation under OTG controllers.

 Documentation/devicetree/bindings/usb/generic.txt |  3 +++
 drivers/usb/common/usb-otg.c                      | 32 ++++++++++++++++-------
 include/linux/usb/otg.h                           |  7 ++++-
 3 files changed, 32 insertions(+), 10 deletions(-)

diff --git a/Documentation/devicetree/bindings/usb/generic.txt b/Documentation/devicetree/bindings/usb/generic.txt
index 0887d6e..6013296 100644
--- a/Documentation/devicetree/bindings/usb/generic.txt
+++ b/Documentation/devicetree/bindings/usb/generic.txt
@@ -26,6 +26,9 @@ Optional properties for OTG controllers:
 			optional for OTG device.
  - adp-disable: tells OTG controllers we want to disable OTG ADP, ADP is
 			optional for OTG device.
+ - hcd-needs-companion: must be present if otg controller is dealing with
+			EHCI host controller that needs a companion OHCI host
+			controller.
 
 Optional properties for host/device controllers:
  - otg-controller: phandle to otg controller. Host or gadget controllers can
diff --git a/drivers/usb/common/usb-otg.c b/drivers/usb/common/usb-otg.c
index 64be6df..8a2a0d4 100644
--- a/drivers/usb/common/usb-otg.c
+++ b/drivers/usb/common/usb-otg.c
@@ -18,6 +18,7 @@
 #include <linux/list.h>
 #include <linux/of.h>
 #include <linux/of_platform.h>
+#include <linux/usb/of.h>
 #include <linux/usb/otg.h>
 #include <linux/usb/gadget.h>
 #include <linux/workqueue.h>
@@ -584,6 +585,10 @@ struct usb_otg *usb_otg_register(struct device *dev,
 	else
 		INIT_WORK(&otg->work, usb_drd_work);
 
+	if (of_find_property(dev->of_node, "hcd-needs-companion", NULL) ||
+	    config->hcd_needs_companion)	/* needs companion ? */
+		otg->flags |= OTG_FLAG_HCD_NEEDS_COMPANION;
+
 	otg->wq = create_freezable_workqueue("usb_otg");
 	if (!otg->wq) {
 		dev_err(dev, "otg: %s: can't create workqueue\n",
@@ -807,15 +812,18 @@ int usb_otg_register_hcd(struct usb_hcd *hcd, unsigned int irqnum,
 	/* HCD will be started by OTG fsm when needed */
 	mutex_lock(&otg->fsm.lock);
 	if (otg->primary_hcd.hcd) {
-		/* probably a shared HCD ? */
-		if (usb_otg_hcd_is_primary_hcd(hcd)) {
+		/* probably a shared HCD or a companion OHCI HCD ? */
+		if (!(otg->flags & OTG_FLAG_HCD_NEEDS_COMPANION) &&
+		    usb_otg_hcd_is_primary_hcd(hcd)) {
 			dev_err(otg_dev, "otg: primary host already registered\n");
 			goto err;
 		}
 
-		if (hcd->shared_hcd == otg->primary_hcd.hcd) {
+		if (otg->flags & OTG_FLAG_HCD_NEEDS_COMPANION ||
+		    (hcd->shared_hcd == otg->primary_hcd.hcd)) {
 			if (otg->shared_hcd.hcd) {
-				dev_err(otg_dev, "otg: shared host already registered\n");
+				dev_err(otg_dev,
+					"otg: shared/companion host already registered\n");
 				goto err;
 			}
 
@@ -823,10 +831,12 @@ int usb_otg_register_hcd(struct usb_hcd *hcd, unsigned int irqnum,
 			otg->shared_hcd.irqnum = irqnum;
 			otg->shared_hcd.irqflags = irqflags;
 			otg->shared_hcd.ops = ops;
-			dev_info(otg_dev, "otg: shared host %s registered\n",
+			dev_info(otg_dev,
+				 "otg: shared/companion host %s registered\n",
 				 dev_name(hcd->self.controller));
 		} else {
-			dev_err(otg_dev, "otg: invalid shared host %s\n",
+			dev_err(otg_dev,
+				"otg: invalid shared/companion host %s\n",
 				dev_name(hcd->self.controller));
 			goto err;
 		}
@@ -849,14 +859,17 @@ int usb_otg_register_hcd(struct usb_hcd *hcd, unsigned int irqnum,
 	 * we're ready only if we have shared HCD
 	 * or we don't need shared HCD.
 	 */
-	if (otg->shared_hcd.hcd || !otg->primary_hcd.hcd->shared_hcd) {
+	if (otg->shared_hcd.hcd ||
+	    (!(otg->flags & OTG_FLAG_HCD_NEEDS_COMPANION) &&
+	     !otg->primary_hcd.hcd->shared_hcd)) {
 		otg->host = hcd_to_bus(hcd);
 		/* FIXME: set bus->otg_port if this is true OTG port with HNP */
 
 		/* start FSM */
 		usb_otg_start_fsm(otg);
 	} else {
-		dev_dbg(otg_dev, "otg: can't start till shared host registers\n");
+		dev_dbg(otg_dev,
+			"otg: can't start till shared/companion host registers\n");
 	}
 
 	mutex_unlock(&otg->fsm.lock);
@@ -907,7 +920,8 @@ int usb_otg_unregister_hcd(struct usb_hcd *hcd)
 			 dev_name(hcd_dev));
 	} else if (hcd == otg->shared_hcd.hcd) {
 		otg->shared_hcd.hcd = NULL;
-		dev_info(otg_dev, "otg: shared host %s unregistered\n",
+		dev_info(otg_dev,
+			 "otg: shared/companion host %s unregistered\n",
 			 dev_name(hcd_dev));
 	} else {
 		dev_err(otg_dev, "otg: host %s wasn't registered with otg\n",
diff --git a/include/linux/usb/otg.h b/include/linux/usb/otg.h
index b094352..6f4ca77 100644
--- a/include/linux/usb/otg.h
+++ b/include/linux/usb/otg.h
@@ -57,7 +57,8 @@ struct otg_hcd {
  * @list: list of otg controllers
  * @work: otg state machine work
  * @wq: otg state machine work queue
- * @flags: to track if host/gadget is running
+ * @flags: to track if host/gadget is running, or to indicate if hcd needs
+ *	   companion
  */
 struct usb_otg {
 	u8			default_a;
@@ -84,6 +85,7 @@ struct usb_otg {
 	u32 flags;
 #define OTG_FLAG_GADGET_RUNNING (1 << 0)
 #define OTG_FLAG_HOST_RUNNING (1 << 1)
+#define OTG_FLAG_HCD_NEEDS_COMPANION (1 << 2)
 	/* use otg->fsm.lock for serializing access */
 
 /*------------- deprecated interface -----------------------------*/
@@ -125,11 +127,14 @@ struct usb_otg_caps {
  * @caps: otg capabilities of the controller
  * @ops: otg fsm operations
  * @otg_work: optional custom otg state machine work function
+ * @hcd_needs_companion: Indicates if host controller needs a companion
+ *			 controller
  */
 struct usb_otg_config {
 	struct usb_otg_caps *otg_caps;
 	struct otg_fsm_ops *fsm_ops;
 	void (*otg_work)(struct work_struct *work);
+	bool hcd_needs_companion;
 };
 
 extern const char *usb_otg_state_string(enum usb_otg_state state);
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* Re: [PATCH v8 08/14] usb: otg: add OTG/dual-role core
  2016-05-20  9:19           ` Roger Quadros
@ 2016-05-20  9:53             ` Peter Chen
  2016-05-23 10:06               ` Roger Quadros
  0 siblings, 1 reply; 62+ messages in thread
From: Peter Chen @ 2016-05-20  9:53 UTC (permalink / raw)
  To: Roger Quadros
  Cc: Peter Chen, balbi, tony, Greg Kroah-Hartman, dan.j.williams,
	mathias.nyman, Joao.Pinto, sergei.shtylyov, jun.li,
	grygorii.strashko, yoshihiro.shimoda.uh, robh, nsekhar, b-liu,
	linux-usb, linux-omap, lkml, devicetree

On Fri, May 20, 2016 at 12:19:07PM +0300, Roger Quadros wrote:
> On 20/05/16 11:31, Roger Quadros wrote:
> > On 18/05/16 15:59, Roger Quadros wrote:
> >> Hi Peter,
> >>
> >> On 18/05/16 10:45, Peter Chen wrote:
> >>>
> >>>
> >>> On Mon, May 16, 2016 at 5:00 PM, Roger Quadros <rogerq@ti.com <mailto:rogerq@ti.com>> wrote:
> >>>
> >>>     On 13/05/16 13:03, Roger Quadros wrote:
> >>>     > It provides APIs for the following tasks
> >>>     >
> >>>     > - Registering an OTG/dual-role capable controller
> >>>     > - Registering Host and Gadget controllers to OTG core
> >>>     > - Providing inputs to and kicking the OTG state machine
> >>>     >
> >>>     > Provide a dual-role device (DRD) state machine.
> >>>     > DRD mode is a reduced functionality OTG mode. In this mode
> >>>     > we don't support SRP, HNP and dynamic role-swap.
> >>>     >
> >>>     > In DRD operation, the controller mode (Host or Peripheral)
> >>>     > is decided based on the ID pin status. Once a cable plug (Type-A
> >>>     > or Type-B) is attached the controller selects the state
> >>>     > and doesn't change till the cable in unplugged and a different
> >>>     > cable type is inserted.
> >>>     >
> >>>     > As we don't need most of the complex OTG states and OTG timers
> >>>     > we implement a lean DRD state machine in usb-otg.c.
> >>>     > The DRD state machine is only interested in 2 hardware inputs
> >>>     > 'id' and 'b_sess_vld'.
> >>>     >
> >>>     > Signed-off-by: Roger Quadros <rogerq@ti.com <mailto:rogerq@ti.com>>
> >>>     > ---
> >>>     >  drivers/usb/common/Makefile  |    2 +-
> >>>     >  drivers/usb/common/usb-otg.c | 1042 ++++++++++++++++++++++++++++++++++++++++++
> >>>     >  drivers/usb/core/Kconfig     |    4 +-
> >>>     >  include/linux/usb/gadget.h   |    2 +
> >>>     >  include/linux/usb/hcd.h      |    1 +
> >>>     >  include/linux/usb/otg-fsm.h  |    7 +
> >>>     >  include/linux/usb/otg.h      |  154 ++++++-
> >>>     >  7 files changed, 1206 insertions(+), 6 deletions(-)
> >>>     >  create mode 100644 drivers/usb/common/usb-otg.c
> >>>
> >>>
> >>>     This patch causes the following build issues when CONFIG_USB_GADGET=m, CONFIG_USB=m,
> >>>     CONFIG_USB_COMMON=m and CONFIG_USB_OTG=y
> >>>
> >>>     ERROR: "usb_otg_register_gadget" [drivers/usb/gadget/udc/udc-core.ko] undefined!
> >>>     ERROR: "usb_otg_unregister_gadget" [drivers/usb/gadget/udc/udc-core.ko] undefined!
> >>>     ERROR: "usb_otg_register_hcd" [drivers/usb/core/usbcore.ko] undefined!
> >>>     ERROR: "usb_otg_unregister_hcd" [drivers/usb/core/usbcore.ko] undefined!
> >>>     ERROR: "otg_statemachine" [drivers/usb/chipidea/ci_hdrc.ko] undefined!
> >>>     scripts/Makefile.modpost:91: recipe for target '__modpost' failed
> >>>     make[1]: *** [__modpost] Error 1
> >>>     Makefile:1141: recipe for target 'modules' failed
> >>>     make: *** [modules] Error 2
> >>>     make: *** Waiting for unfinished jobs....
> >>>
> >>>     drivers/built-in.o: In function `drd_set_state':
> >>>     usb-otg.c:(.text+0x2b4242): undefined reference to `usb_otg_state_string'
> >>>     drivers/built-in.o: In function `drd_statemachine':
> >>>     (.text+0x2b4b4c): undefined reference to `usb_otg_state_string'
> >>>     Makefile:937: recipe for target 'vmlinux' failed
> >>>
> >>>     I'll fix it up with the following diff.
> >>>
> >>>     diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile
> >>>     index dca7856..16a5b55 100644
> >>>     --- a/drivers/usb/Makefile
> >>>     +++ b/drivers/usb/Makefile
> >>>     @@ -59,5 +59,6 @@ obj-$(CONFIG_USB_RENESAS_USBHS)       += renesas_usbhs/
> >>>      obj-$(CONFIG_USB_GADGET)       += gadget/
> >>>
> >>>      obj-$(CONFIG_USB_COMMON)       += common/
> >>>     +obj-$(CONFIG_USB_OTG)          += common/
> >>>
> >>>      obj-$(CONFIG_USBIP_CORE)       += usbip/
> >>>     diff --git a/drivers/usb/common/usb-otg.c b/drivers/usb/common/usb-otg.c
> >>>     index 77048aa..17e449e 100644
> >>>     --- a/drivers/usb/common/usb-otg.c
> >>>     +++ b/drivers/usb/common/usb-otg.c
> >>>     @@ -56,6 +56,30 @@ static int usb_otg_hcd_is_primary_hcd(struct usb_hcd *hcd)
> >>>             return hcd == hcd->primary_hcd;
> >>>      }
> >>>
> >>>     +static const char *otg_state_string(enum usb_otg_state state)
> >>>     +{
> >>>     +       static const char *const names[] = {
> >>>     +               [OTG_STATE_A_IDLE] = "a_idle",
> >>>     +               [OTG_STATE_A_WAIT_VRISE] = "a_wait_vrise",
> >>>     +               [OTG_STATE_A_WAIT_BCON] = "a_wait_bcon",
> >>>     +               [OTG_STATE_A_HOST] = "a_host",
> >>>     +               [OTG_STATE_A_SUSPEND] = "a_suspend",
> >>>     +               [OTG_STATE_A_PERIPHERAL] = "a_peripheral",
> >>>     +               [OTG_STATE_A_WAIT_VFALL] = "a_wait_vfall",
> >>>     +               [OTG_STATE_A_VBUS_ERR] = "a_vbus_err",
> >>>     +               [OTG_STATE_B_IDLE] = "b_idle",
> >>>     +               [OTG_STATE_B_SRP_INIT] = "b_srp_init",
> >>>     +               [OTG_STATE_B_PERIPHERAL] = "b_peripheral",
> >>>     +               [OTG_STATE_B_WAIT_ACON] = "b_wait_acon",
> >>>     +               [OTG_STATE_B_HOST] = "b_host",
> >>>     +       };
> >>>     +
> >>>     +       if (state < 0 || state >= ARRAY_SIZE(names))
> >>>     +               return "UNDEFINED";
> >>>     +
> >>>     +       return names[state];
> >>>     +}
> >>>     +
> >>>
> >>>
> >>>
> >>> From my point, make another copy for otg stuff is not a good way,
> >>> could we make folder under usb/ named otg for dedicated otg stuffs,
> >>> in that case, build otg stuffs can not depend on USB_COMMON.
> >>
> >> OK. I can try that. I'll delete otg_state_string from usb-common.c and
> >> move it into usb/otg/usb-otg.c
> >>
> >> I'll also move usb-otg-fsm.c to usb/otg/.
> > 
> > But we can't delete usb_otg_state_string() from usb-common.c. That is used at a
> > number of places whether OTG is enabled or not. 
> > 
> > One option is to make usb-common built in when otg is enabled. What do you say?
> > 
> 
> This should also get solved if we make USB_OTG tristate so that it is same as
> USB_COMMON.
> 
> However I haven't had success in making Kconfig behave like this.
> 
> USB_OTG = y if USB == y && GADGET = m
> USB_OTG = y if USB == m && GADGET = y
> 
> Is there any Kconfig trickery to get this behaviour?
> 

Unless let the USB_OTG works like USB_COMMON which is selected by GADGET
or HCD. In fact, HCD and Gadget code uses USB OTG symbol directly in
this framework, it seems like HCD and Gadget depends on OTG, but not
otherwise.

If we want OTG to depend on HCD && GADGET, we need not to use OTG symbol
at HCD and GADGET, and the OTG can use HCD and GADGET symbol directly.

-- 

Best Regards,
Peter Chen

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v8 13/14] usb: gadget: udc: adapt to OTG core
  2016-05-19  7:32                         ` Roger Quadros
@ 2016-05-21  2:29                           ` Peter Chen
  2016-05-23  3:21                             ` Peter Chen
  0 siblings, 1 reply; 62+ messages in thread
From: Peter Chen @ 2016-05-21  2:29 UTC (permalink / raw)
  To: Roger Quadros
  Cc: Jun Li, peter.chen, balbi, tony, gregkh, dan.j.williams,
	mathias.nyman, Joao.Pinto, sergei.shtylyov, jun.li,
	grygorii.strashko, yoshihiro.shimoda.uh, robh, nsekhar, b-liu,
	linux-usb, linux-omap, linux-kernel, devicetree

On Thu, May 19, 2016 at 10:32:44AM +0300, Roger Quadros wrote:
> On 18/05/16 17:46, Jun Li wrote:
> > 
> > 
> >>>>
> >>>> I didn't want to have complex Kconfig so decided to have otg as
> >>>> built-in only.
> >>>> What do you want me to change in existing code? and why?
> >>>
> >>> Remove those stuff which only for pass diff driver config Like every
> >>> controller driver need a duplicated
> >>>
> >>> static struct otg_hcd_ops ci_hcd_ops = {
> >>>     ...
> >>> }
> >>
> >> This is an exception only. Every controller driver doesn't need to
> >> implement hcd_ops. It is implemented in the hcd core.
> >>
> >>>
> >>> And here is another example, for gadget connect, otg driver can
> >>> directly call to usb_udc_vbus_handler() in drd state machine, but you
> >>> create another interface:
> >>>
> >>> .connect_control = usb_gadget_connect_control,
> >>>
> >>> If the symbol is defined in one driver which is 'm', another driver
> >>> reference it should be 'm' as well, then there is no this kind of
> >>> problem as my understanding.
> >>
> >> That is fine as long as all are 'm'. but how do you solve the case when
> >> Gadget is built in and host is 'm'? OTG has to be built-in and you will
> >> need an hcd to gadget interface.
> > 
> > Hcd to gadget interface? Or you want to say otg to host interface?
> 
> Sorry, I meant to say host to otg interface.
> 
> > 
> > I think hcd and gadget are independent each other, now
> > 
> > Hcd --> otg; and gadget --> otg, (hcd and gadget use otg's symbol)
> 
> It is actually a circular dependency for both.
>  hcd <--> otg and gadget <--> otg
> 
> hcd -> otg for usb_otg_register/unregister_hcd
> otg -> hcd for usb_add/remove_hcd, usb_bus_start_enum, usb_control_msg, usb_hub_find_child
> 
> gadget -> otg for usb_otg_register/unregister_gadget
> otg -> gadget for usb_gadget_start/stop, usb_udc_vbus_handler
> 
> Now consider what will happen if I get rid of the otg_hcd and otg_gadget interfaces.
> 'y' means built-in, 'm' means module.
> 
> 1) hcd 'y', gadget 'y'
> otg has to be 'y' for proper build.
> 
> 2) hcd 'm', gadget 'm'
> otg has to be 'm' for proper build.
> 
> 3) hcd 'y', gadget 'm'
> Build will fail always.
> If otg is 'y', otg build will fail due to dependency on gadget.
> If otg is 'm', hcd build will fail due to dependency on otg.
> 
> 4) hcd 'm', gadget 'y'
> Build will fail always.
> If otg is 'y', otg build will fail due to dependency on hcd.
> If otg is 'm', gadget build will fails due to dependency on otg.
> 
> So I solve this problem by adding the otg_hcd_ops and otg_gadget_ops
> to remove otg->hcd and otg->gadget dependency.
> 
> Now we can address 3) and 4) like so
> 
> 3) hcd 'y', gadget 'm'
> otg has to be 'y' for proper build.
> 
> 4) hcd 'm', gadget 'y'
> otg has to be 'y' for proper build.
> 

How about this:
Moving usb_otg_register/unregister_hcd to host driver to remove
dependency hcd->otg. And moving usb_otg_get_data to common.c.

Delete the wait queue at usb-otg.c, and if calling usb_otg_get_data
returns NULL, the host/device driver's probe return -EPROBE_DEFER.
When the otg driver is probed successfully, the host/device will be
re-probed again, and usb_otg_register_hcd will be called again.

And let OTG depends on HCD && GADGET, and delete otg_hcd_ops and
otg_gadget_ops. Below build dependency issues can be fixed.
What do you think?

> 1) hcd 'y', gadget 'y'
> otg has to be 'y' for proper build.
> 
> 2) hcd 'm', gadget 'm'
> otg has to be 'm' for proper build.
> 
> 3) hcd 'y', gadget 'm'
> Build will fail always.
> If otg is 'y', otg build will fail due to dependency on gadget.
> If otg is 'm', hcd build will fail due to dependency on otg.
> 
> 4) hcd 'm', gadget 'y'
> Build will fail always.
> If otg is 'y', otg build will fail due to dependency on hcd.
> If otg is 'm', gadget build will fails due to dependency on otg.
-- 

Best Regards,
Peter Chen

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v8 13/14] usb: gadget: udc: adapt to OTG core
  2016-05-20  7:26                 ` Roger Quadros
@ 2016-05-21  2:44                   ` Peter Chen
  0 siblings, 0 replies; 62+ messages in thread
From: Peter Chen @ 2016-05-21  2:44 UTC (permalink / raw)
  To: Roger Quadros
  Cc: peter.chen, balbi, tony, gregkh, dan.j.williams, mathias.nyman,
	Joao.Pinto, sergei.shtylyov, jun.li, grygorii.strashko,
	yoshihiro.shimoda.uh, robh, nsekhar, b-liu, linux-usb,
	linux-omap, linux-kernel, devicetree

On Fri, May 20, 2016 at 10:26:03AM +0300, Roger Quadros wrote:
> Peter,
> 
> On 20/05/16 04:39, Peter Chen wrote:
> > On Wed, May 18, 2016 at 03:45:11PM +0300, Roger Quadros wrote:
> >> On 18/05/16 06:18, Peter Chen wrote:
> >>> On Mon, May 16, 2016 at 12:51:53PM +0300, Roger Quadros wrote:
> >>>> On 16/05/16 12:23, Peter Chen wrote:
> >>>>> On Mon, May 16, 2016 at 11:26:57AM +0300, Roger Quadros wrote:
> >>>>>> Hi,
> >>>>>>
> >>>>>> On 16/05/16 10:02, Peter Chen wrote:
> >>>>>>> On Fri, May 13, 2016 at 01:03:27PM +0300, Roger Quadros wrote:
> >>>>>>>> +
> >>>>>>>> +static int usb_gadget_connect_control(struct usb_gadget *gadget, bool connect)
> >>>>>>>> +{
> >>>>>>>> +	struct usb_udc *udc;
> >>>>>>>> +
> >>>>>>>> +	mutex_lock(&udc_lock);
> >>>>>>>> +	udc = usb_gadget_to_udc(gadget);
> >>>>>>>> +	if (!udc) {
> >>>>>>>> +		dev_err(gadget->dev.parent, "%s: gadget not registered.\n",
> >>>>>>>> +			__func__);
> >>>>>>>> +		mutex_unlock(&udc_lock);
> >>>>>>>> +		return -EINVAL;
> >>>>>>>> +	}
> >>>>>>>> +
> >>>>>>>> +	if (connect) {
> >>>>>>>> +		if (!gadget->connected)
> >>>>>>>> +			usb_gadget_connect(udc->gadget);
> >>>>>>>> +	} else {
> >>>>>>>> +		if (gadget->connected) {
> >>>>>>>> +			usb_gadget_disconnect(udc->gadget);
> >>>>>>>> +			udc->driver->disconnect(udc->gadget);
> >>>>>>>> +		}
> >>>>>>>> +	}
> >>>>>>>> +
> >>>>>>>> +	mutex_unlock(&udc_lock);
> >>>>>>>> +
> >>>>>>>> +	return 0;
> >>>>>>>> +}
> >>>>>>>> +
> >>>>>>>
> >>>>>>> Since this is called for vbus interrupt, why not using
> >>>>>>> usb_udc_vbus_handler directly, and call udc->driver->disconnect
> >>>>>>> at usb_gadget_stop.
> >>>>>>
> >>>>>> We can't assume that this is always called for vbus interrupt so
> >>>>>> I decided not to call usb_udc_vbus_handler.
> >>>>>>
> >>>>>> udc->vbus is really pointless for us. We keep vbus states in our
> >>>>>> state machine and leave udc->vbus as ture always.
> >>>>>>
> >>>>>> Why do you want to move udc->driver->disconnect() to stop?
> >>>>>> If USB controller disconnected from bus then the gadget driver
> >>>>>> must be notified about the disconnect immediately. The controller
> >>>>>> may or may not be stopped by the core.
> >>>>>>
> >>>>>
> >>>>> Then, would you give some comments when this API will be used?
> >>>>> I was assumed it is only used for drd state machine.
> >>>>
> >>>> drd_state machine didn't even need this API in the first place :).
> >>>> You guys wanted me to separate out start/stop and connect/disconnect for full OTG case.
> >>>> Won't full OTG state machine want to use this API? If not what would it use?
> >>>>
> >>>
> >>> Oh, I meant only drd and fully otg state machine needs it. I am
> >>> wondering if we need have a new API to do it. Two questions:
> >>
> >> OK.
> >>>
> >>> - Except for vbus interrupt, any chances this API will be used at
> >>> current logic?
> >>
> >> I don't think so. But we can't assume caller behaviour for any API.
> >>
> >>> - When this API is called but without a coming gadget->stop?
> >>>
> >> Never for DRD case. But we want to catch wrong users.
> >>
> > 
> > In future, otg_start_gadget will be used for both DRD and fully OTG FSM.
> > There is no otg_loc_conn at current DRD FSM, but there is
> > otg_loc_conn at current OTG FSM, see below.
> > 
> > DRD FSM:
> > 	case OTG_STATE_B_IDLE:
> > 		drd_set_protocol(fsm, PROTO_UNDEF);
> > 		otg_drv_vbus(otg, 0);
> > 		break;
> > 	case OTG_STATE_B_PERIPHERAL:
> > 		drd_set_protocol(fsm, PROTO_GADGET);
> > 		otg_drv_vbus(otg, 0);
> > 		break;
> > 
> > OTG FSM:
> > 	case OTG_STATE_B_IDLE:
> > 		otg_drv_vbus(otg, 0);
> > 		otg_chrg_vbus(otg, 0);
> > 		otg_loc_conn(otg, 0);
> > 		otg_loc_sof(otg, 0);
> > 		/*
> > 		 * Driver is responsible for starting ADP probing
> > 		 * if ADP sensing times out.
> > 		 */
> > 		otg_start_adp_sns(otg);
> > 		otg_set_protocol(fsm, PROTO_UNDEF);
> > 		otg_add_timer(otg, B_SE0_SRP);
> > 		break;
> > 	case OTG_STATE_B_PERIPHERAL:
> > 		otg_chrg_vbus(otg, 0);
> > 		otg_loc_sof(otg, 0);
> > 		otg_set_protocol(fsm, PROTO_GADGET);
> > 		otg_loc_conn(otg, 1);
> > 		break;
> > 
> > My original suggestion is to have an API to do pull dp and this API
> > will be used at both DRD and OTG FSM, and called at otg_loc_conn.
> 
> The API is usb_gadget_connect_control();
> 
> > The (de)initialize is the same for both two FSMs, it both includes
> > init peripheral mode and pull up dp, and can be done by drd_set_protocol(fsm, PROTO_GADGET)
> > otg_loc_conn(otg, 1);
> > 
> > What do you think?
> > 
> 
> I think loc_conn is a bit confusing to drd users. Another issue I see is that 
> DRD controller drivers will need to explicitly pass .loc_conn ops via the otg_fsm_ops.
> This is an additional step and totally unnecessary as it can be automatically done
> via direct DRD -> UDC-core call.
> 

If you are stick to that, let's follow your way if Felipe agree with it
too, although it lets the DRD state machine look different with OTG's.

-- 

Best Regards,
Peter Chen

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v8 13/14] usb: gadget: udc: adapt to OTG core
  2016-05-21  2:29                           ` Peter Chen
@ 2016-05-23  3:21                             ` Peter Chen
  2016-05-23 10:11                               ` Roger Quadros
  0 siblings, 1 reply; 62+ messages in thread
From: Peter Chen @ 2016-05-23  3:21 UTC (permalink / raw)
  To: Roger Quadros
  Cc: Jun Li, peter.chen, balbi, tony, gregkh, dan.j.williams,
	mathias.nyman, Joao.Pinto, sergei.shtylyov, jun.li,
	grygorii.strashko, yoshihiro.shimoda.uh, robh, nsekhar, b-liu,
	linux-usb, linux-omap, linux-kernel, devicetree

On Sat, May 21, 2016 at 10:29:40AM +0800, Peter Chen wrote:
> On Thu, May 19, 2016 at 10:32:44AM +0300, Roger Quadros wrote:
> > On 18/05/16 17:46, Jun Li wrote:
> > > 
> > > 
> > >>>>
> > >>>> I didn't want to have complex Kconfig so decided to have otg as
> > >>>> built-in only.
> > >>>> What do you want me to change in existing code? and why?
> > >>>
> > >>> Remove those stuff which only for pass diff driver config Like every
> > >>> controller driver need a duplicated
> > >>>
> > >>> static struct otg_hcd_ops ci_hcd_ops = {
> > >>>     ...
> > >>> }
> > >>
> > >> This is an exception only. Every controller driver doesn't need to
> > >> implement hcd_ops. It is implemented in the hcd core.
> > >>
> > >>>
> > >>> And here is another example, for gadget connect, otg driver can
> > >>> directly call to usb_udc_vbus_handler() in drd state machine, but you
> > >>> create another interface:
> > >>>
> > >>> .connect_control = usb_gadget_connect_control,
> > >>>
> > >>> If the symbol is defined in one driver which is 'm', another driver
> > >>> reference it should be 'm' as well, then there is no this kind of
> > >>> problem as my understanding.
> > >>
> > >> That is fine as long as all are 'm'. but how do you solve the case when
> > >> Gadget is built in and host is 'm'? OTG has to be built-in and you will
> > >> need an hcd to gadget interface.
> > > 
> > > Hcd to gadget interface? Or you want to say otg to host interface?
> > 
> > Sorry, I meant to say host to otg interface.
> > 
> > > 
> > > I think hcd and gadget are independent each other, now
> > > 
> > > Hcd --> otg; and gadget --> otg, (hcd and gadget use otg's symbol)
> > 
> > It is actually a circular dependency for both.
> >  hcd <--> otg and gadget <--> otg
> > 
> > hcd -> otg for usb_otg_register/unregister_hcd
> > otg -> hcd for usb_add/remove_hcd, usb_bus_start_enum, usb_control_msg, usb_hub_find_child
> > 
> > gadget -> otg for usb_otg_register/unregister_gadget
> > otg -> gadget for usb_gadget_start/stop, usb_udc_vbus_handler
> > 
> > Now consider what will happen if I get rid of the otg_hcd and otg_gadget interfaces.
> > 'y' means built-in, 'm' means module.
> > 
> > 1) hcd 'y', gadget 'y'
> > otg has to be 'y' for proper build.
> > 
> > 2) hcd 'm', gadget 'm'
> > otg has to be 'm' for proper build.
> > 
> > 3) hcd 'y', gadget 'm'
> > Build will fail always.
> > If otg is 'y', otg build will fail due to dependency on gadget.
> > If otg is 'm', hcd build will fail due to dependency on otg.
> > 
> > 4) hcd 'm', gadget 'y'
> > Build will fail always.
> > If otg is 'y', otg build will fail due to dependency on hcd.
> > If otg is 'm', gadget build will fails due to dependency on otg.
> > 
> > So I solve this problem by adding the otg_hcd_ops and otg_gadget_ops
> > to remove otg->hcd and otg->gadget dependency.
> > 
> > Now we can address 3) and 4) like so
> > 
> > 3) hcd 'y', gadget 'm'
> > otg has to be 'y' for proper build.
> > 
> > 4) hcd 'm', gadget 'y'
> > otg has to be 'y' for proper build.
> > 
> 
> How about this:
> Moving usb_otg_register/unregister_hcd to host driver to remove
> dependency hcd->otg. And moving usb_otg_get_data to common.c.
> 
> Delete the wait queue at usb-otg.c, and if calling usb_otg_get_data
> returns NULL, the host/device driver's probe return -EPROBE_DEFER.
> When the otg driver is probed successfully, the host/device will be
> re-probed again, and usb_otg_register_hcd will be called again.
> 
> And let OTG depends on HCD && GADGET, and delete otg_hcd_ops and
> otg_gadget_ops. Below build dependency issues can be fixed.
> What do you think?
> 
> > 1) hcd 'y', gadget 'y'
> > otg has to be 'y' for proper build.
> > 
> > 2) hcd 'm', gadget 'm'
> > otg has to be 'm' for proper build.
> > 
> > 3) hcd 'y', gadget 'm'
> > Build will fail always.
> > If otg is 'y', otg build will fail due to dependency on gadget.
> > If otg is 'm', hcd build will fail due to dependency on otg.
> > 
> > 4) hcd 'm', gadget 'y'
> > Build will fail always.
> > If otg is 'y', otg build will fail due to dependency on hcd.
> > If otg is 'm', gadget build will fails due to dependency on otg.
> -- 
> 

After thinking more, my suggestion can't work. How about moving
CONFIG_USB_OTG out of CONFIG_USB, in that case, CONFIG_USB_OTG
can only be built in.

-- 

Best Regards,
Peter Chen

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v8 08/14] usb: otg: add OTG/dual-role core
  2016-05-20  9:53             ` Peter Chen
@ 2016-05-23 10:06               ` Roger Quadros
  0 siblings, 0 replies; 62+ messages in thread
From: Roger Quadros @ 2016-05-23 10:06 UTC (permalink / raw)
  To: Peter Chen
  Cc: Peter Chen, balbi, tony, Greg Kroah-Hartman, dan.j.williams,
	mathias.nyman, Joao.Pinto, sergei.shtylyov, jun.li,
	grygorii.strashko, yoshihiro.shimoda.uh, robh, nsekhar, b-liu,
	linux-usb, linux-omap, lkml, devicetree

On 20/05/16 12:53, Peter Chen wrote:
> On Fri, May 20, 2016 at 12:19:07PM +0300, Roger Quadros wrote:
>> On 20/05/16 11:31, Roger Quadros wrote:
>>> On 18/05/16 15:59, Roger Quadros wrote:
>>>> Hi Peter,
>>>>
>>>> On 18/05/16 10:45, Peter Chen wrote:
>>>>>
>>>>>
>>>>> On Mon, May 16, 2016 at 5:00 PM, Roger Quadros <rogerq@ti.com <mailto:rogerq@ti.com>> wrote:
>>>>>
>>>>>     On 13/05/16 13:03, Roger Quadros wrote:
>>>>>     > It provides APIs for the following tasks
>>>>>     >
>>>>>     > - Registering an OTG/dual-role capable controller
>>>>>     > - Registering Host and Gadget controllers to OTG core
>>>>>     > - Providing inputs to and kicking the OTG state machine
>>>>>     >
>>>>>     > Provide a dual-role device (DRD) state machine.
>>>>>     > DRD mode is a reduced functionality OTG mode. In this mode
>>>>>     > we don't support SRP, HNP and dynamic role-swap.
>>>>>     >
>>>>>     > In DRD operation, the controller mode (Host or Peripheral)
>>>>>     > is decided based on the ID pin status. Once a cable plug (Type-A
>>>>>     > or Type-B) is attached the controller selects the state
>>>>>     > and doesn't change till the cable in unplugged and a different
>>>>>     > cable type is inserted.
>>>>>     >
>>>>>     > As we don't need most of the complex OTG states and OTG timers
>>>>>     > we implement a lean DRD state machine in usb-otg.c.
>>>>>     > The DRD state machine is only interested in 2 hardware inputs
>>>>>     > 'id' and 'b_sess_vld'.
>>>>>     >
>>>>>     > Signed-off-by: Roger Quadros <rogerq@ti.com <mailto:rogerq@ti.com>>
>>>>>     > ---
>>>>>     >  drivers/usb/common/Makefile  |    2 +-
>>>>>     >  drivers/usb/common/usb-otg.c | 1042 ++++++++++++++++++++++++++++++++++++++++++
>>>>>     >  drivers/usb/core/Kconfig     |    4 +-
>>>>>     >  include/linux/usb/gadget.h   |    2 +
>>>>>     >  include/linux/usb/hcd.h      |    1 +
>>>>>     >  include/linux/usb/otg-fsm.h  |    7 +
>>>>>     >  include/linux/usb/otg.h      |  154 ++++++-
>>>>>     >  7 files changed, 1206 insertions(+), 6 deletions(-)
>>>>>     >  create mode 100644 drivers/usb/common/usb-otg.c
>>>>>
>>>>>
>>>>>     This patch causes the following build issues when CONFIG_USB_GADGET=m, CONFIG_USB=m,
>>>>>     CONFIG_USB_COMMON=m and CONFIG_USB_OTG=y
>>>>>
>>>>>     ERROR: "usb_otg_register_gadget" [drivers/usb/gadget/udc/udc-core.ko] undefined!
>>>>>     ERROR: "usb_otg_unregister_gadget" [drivers/usb/gadget/udc/udc-core.ko] undefined!
>>>>>     ERROR: "usb_otg_register_hcd" [drivers/usb/core/usbcore.ko] undefined!
>>>>>     ERROR: "usb_otg_unregister_hcd" [drivers/usb/core/usbcore.ko] undefined!
>>>>>     ERROR: "otg_statemachine" [drivers/usb/chipidea/ci_hdrc.ko] undefined!
>>>>>     scripts/Makefile.modpost:91: recipe for target '__modpost' failed
>>>>>     make[1]: *** [__modpost] Error 1
>>>>>     Makefile:1141: recipe for target 'modules' failed
>>>>>     make: *** [modules] Error 2
>>>>>     make: *** Waiting for unfinished jobs....
>>>>>
>>>>>     drivers/built-in.o: In function `drd_set_state':
>>>>>     usb-otg.c:(.text+0x2b4242): undefined reference to `usb_otg_state_string'
>>>>>     drivers/built-in.o: In function `drd_statemachine':
>>>>>     (.text+0x2b4b4c): undefined reference to `usb_otg_state_string'
>>>>>     Makefile:937: recipe for target 'vmlinux' failed
>>>>>
>>>>>     I'll fix it up with the following diff.
>>>>>
>>>>>     diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile
>>>>>     index dca7856..16a5b55 100644
>>>>>     --- a/drivers/usb/Makefile
>>>>>     +++ b/drivers/usb/Makefile
>>>>>     @@ -59,5 +59,6 @@ obj-$(CONFIG_USB_RENESAS_USBHS)       += renesas_usbhs/
>>>>>      obj-$(CONFIG_USB_GADGET)       += gadget/
>>>>>
>>>>>      obj-$(CONFIG_USB_COMMON)       += common/
>>>>>     +obj-$(CONFIG_USB_OTG)          += common/
>>>>>
>>>>>      obj-$(CONFIG_USBIP_CORE)       += usbip/
>>>>>     diff --git a/drivers/usb/common/usb-otg.c b/drivers/usb/common/usb-otg.c
>>>>>     index 77048aa..17e449e 100644
>>>>>     --- a/drivers/usb/common/usb-otg.c
>>>>>     +++ b/drivers/usb/common/usb-otg.c
>>>>>     @@ -56,6 +56,30 @@ static int usb_otg_hcd_is_primary_hcd(struct usb_hcd *hcd)
>>>>>             return hcd == hcd->primary_hcd;
>>>>>      }
>>>>>
>>>>>     +static const char *otg_state_string(enum usb_otg_state state)
>>>>>     +{
>>>>>     +       static const char *const names[] = {
>>>>>     +               [OTG_STATE_A_IDLE] = "a_idle",
>>>>>     +               [OTG_STATE_A_WAIT_VRISE] = "a_wait_vrise",
>>>>>     +               [OTG_STATE_A_WAIT_BCON] = "a_wait_bcon",
>>>>>     +               [OTG_STATE_A_HOST] = "a_host",
>>>>>     +               [OTG_STATE_A_SUSPEND] = "a_suspend",
>>>>>     +               [OTG_STATE_A_PERIPHERAL] = "a_peripheral",
>>>>>     +               [OTG_STATE_A_WAIT_VFALL] = "a_wait_vfall",
>>>>>     +               [OTG_STATE_A_VBUS_ERR] = "a_vbus_err",
>>>>>     +               [OTG_STATE_B_IDLE] = "b_idle",
>>>>>     +               [OTG_STATE_B_SRP_INIT] = "b_srp_init",
>>>>>     +               [OTG_STATE_B_PERIPHERAL] = "b_peripheral",
>>>>>     +               [OTG_STATE_B_WAIT_ACON] = "b_wait_acon",
>>>>>     +               [OTG_STATE_B_HOST] = "b_host",
>>>>>     +       };
>>>>>     +
>>>>>     +       if (state < 0 || state >= ARRAY_SIZE(names))
>>>>>     +               return "UNDEFINED";
>>>>>     +
>>>>>     +       return names[state];
>>>>>     +}
>>>>>     +
>>>>>
>>>>>
>>>>>
>>>>> From my point, make another copy for otg stuff is not a good way,
>>>>> could we make folder under usb/ named otg for dedicated otg stuffs,
>>>>> in that case, build otg stuffs can not depend on USB_COMMON.
>>>>
>>>> OK. I can try that. I'll delete otg_state_string from usb-common.c and
>>>> move it into usb/otg/usb-otg.c
>>>>
>>>> I'll also move usb-otg-fsm.c to usb/otg/.
>>>
>>> But we can't delete usb_otg_state_string() from usb-common.c. That is used at a
>>> number of places whether OTG is enabled or not. 
>>>
>>> One option is to make usb-common built in when otg is enabled. What do you say?
>>>
>>
>> This should also get solved if we make USB_OTG tristate so that it is same as
>> USB_COMMON.
>>
>> However I haven't had success in making Kconfig behave like this.
>>
>> USB_OTG = y if USB == y && GADGET = m
>> USB_OTG = y if USB == m && GADGET = y
>>
>> Is there any Kconfig trickery to get this behaviour?
>>
> 
> Unless let the USB_OTG works like USB_COMMON which is selected by GADGET
> or HCD. In fact, HCD and Gadget code uses USB OTG symbol directly in
> this framework, it seems like HCD and Gadget depends on OTG, but not
> otherwise.

Not necessarily for build. We have dummy otg functions if USB_OTG is not defined,
and we have checks in place if OTG drivers use OTG related functions while
USB_OTG is not enabled.

> 
> If we want OTG to depend on HCD && GADGET, we need not to use OTG symbol
> at HCD and GADGET, and the OTG can use HCD and GADGET symbol directly.
> 

We can't use select as we don't want USB_OTG enabled when only one of HCD or GADGET
is enabled. We also want users to be able to disable USB_OTG when both HCD and
GADGET are enabled.

cheers,
-roger

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v8 13/14] usb: gadget: udc: adapt to OTG core
  2016-05-23  3:21                             ` Peter Chen
@ 2016-05-23 10:11                               ` Roger Quadros
  2016-05-23 10:34                                 ` Jun Li
  0 siblings, 1 reply; 62+ messages in thread
From: Roger Quadros @ 2016-05-23 10:11 UTC (permalink / raw)
  To: Peter Chen
  Cc: Jun Li, peter.chen, balbi, tony, gregkh, dan.j.williams,
	mathias.nyman, Joao.Pinto, sergei.shtylyov, jun.li,
	grygorii.strashko, yoshihiro.shimoda.uh, robh, nsekhar, b-liu,
	linux-usb, linux-omap, linux-kernel, devicetree

On 23/05/16 06:21, Peter Chen wrote:
> On Sat, May 21, 2016 at 10:29:40AM +0800, Peter Chen wrote:
>> On Thu, May 19, 2016 at 10:32:44AM +0300, Roger Quadros wrote:
>>> On 18/05/16 17:46, Jun Li wrote:
>>>>
>>>>
>>>>>>>
>>>>>>> I didn't want to have complex Kconfig so decided to have otg as
>>>>>>> built-in only.
>>>>>>> What do you want me to change in existing code? and why?
>>>>>>
>>>>>> Remove those stuff which only for pass diff driver config Like every
>>>>>> controller driver need a duplicated
>>>>>>
>>>>>> static struct otg_hcd_ops ci_hcd_ops = {
>>>>>>     ...
>>>>>> }
>>>>>
>>>>> This is an exception only. Every controller driver doesn't need to
>>>>> implement hcd_ops. It is implemented in the hcd core.
>>>>>
>>>>>>
>>>>>> And here is another example, for gadget connect, otg driver can
>>>>>> directly call to usb_udc_vbus_handler() in drd state machine, but you
>>>>>> create another interface:
>>>>>>
>>>>>> .connect_control = usb_gadget_connect_control,
>>>>>>
>>>>>> If the symbol is defined in one driver which is 'm', another driver
>>>>>> reference it should be 'm' as well, then there is no this kind of
>>>>>> problem as my understanding.
>>>>>
>>>>> That is fine as long as all are 'm'. but how do you solve the case when
>>>>> Gadget is built in and host is 'm'? OTG has to be built-in and you will
>>>>> need an hcd to gadget interface.
>>>>
>>>> Hcd to gadget interface? Or you want to say otg to host interface?
>>>
>>> Sorry, I meant to say host to otg interface.
>>>
>>>>
>>>> I think hcd and gadget are independent each other, now
>>>>
>>>> Hcd --> otg; and gadget --> otg, (hcd and gadget use otg's symbol)
>>>
>>> It is actually a circular dependency for both.
>>>  hcd <--> otg and gadget <--> otg
>>>
>>> hcd -> otg for usb_otg_register/unregister_hcd
>>> otg -> hcd for usb_add/remove_hcd, usb_bus_start_enum, usb_control_msg, usb_hub_find_child
>>>
>>> gadget -> otg for usb_otg_register/unregister_gadget
>>> otg -> gadget for usb_gadget_start/stop, usb_udc_vbus_handler
>>>
>>> Now consider what will happen if I get rid of the otg_hcd and otg_gadget interfaces.
>>> 'y' means built-in, 'm' means module.
>>>
>>> 1) hcd 'y', gadget 'y'
>>> otg has to be 'y' for proper build.
>>>
>>> 2) hcd 'm', gadget 'm'
>>> otg has to be 'm' for proper build.
>>>
>>> 3) hcd 'y', gadget 'm'
>>> Build will fail always.
>>> If otg is 'y', otg build will fail due to dependency on gadget.
>>> If otg is 'm', hcd build will fail due to dependency on otg.
>>>
>>> 4) hcd 'm', gadget 'y'
>>> Build will fail always.
>>> If otg is 'y', otg build will fail due to dependency on hcd.
>>> If otg is 'm', gadget build will fails due to dependency on otg.
>>>
>>> So I solve this problem by adding the otg_hcd_ops and otg_gadget_ops
>>> to remove otg->hcd and otg->gadget dependency.
>>>
>>> Now we can address 3) and 4) like so
>>>
>>> 3) hcd 'y', gadget 'm'
>>> otg has to be 'y' for proper build.
>>>
>>> 4) hcd 'm', gadget 'y'
>>> otg has to be 'y' for proper build.
>>>
>>
>> How about this:
>> Moving usb_otg_register/unregister_hcd to host driver to remove
>> dependency hcd->otg. And moving usb_otg_get_data to common.c.
>>
>> Delete the wait queue at usb-otg.c, and if calling usb_otg_get_data
>> returns NULL, the host/device driver's probe return -EPROBE_DEFER.
>> When the otg driver is probed successfully, the host/device will be
>> re-probed again, and usb_otg_register_hcd will be called again.
>>
>> And let OTG depends on HCD && GADGET, and delete otg_hcd_ops and
>> otg_gadget_ops. Below build dependency issues can be fixed.
>> What do you think?
>>
>>> 1) hcd 'y', gadget 'y'
>>> otg has to be 'y' for proper build.
>>>
>>> 2) hcd 'm', gadget 'm'
>>> otg has to be 'm' for proper build.
>>>
>>> 3) hcd 'y', gadget 'm'
>>> Build will fail always.
>>> If otg is 'y', otg build will fail due to dependency on gadget.
>>> If otg is 'm', hcd build will fail due to dependency on otg.
>>>
>>> 4) hcd 'm', gadget 'y'
>>> Build will fail always.
>>> If otg is 'y', otg build will fail due to dependency on hcd.
>>> If otg is 'm', gadget build will fails due to dependency on otg.
>> -- 
>>
> 
> After thinking more, my suggestion can't work. How about moving
> CONFIG_USB_OTG out of CONFIG_USB, in that case, CONFIG_USB_OTG
> can only be built in.
> 
I tried this but it still doesn't resolve 3 and 4. I.e.
it can't be automatically set to 'y' when either of hcd/gadget is 'y'
and the other is 'm'.

I think some kconfig trickery can be done to get what we want.

cheers,
-roger

^ permalink raw reply	[flat|nested] 62+ messages in thread

* RE: [PATCH v8 13/14] usb: gadget: udc: adapt to OTG core
  2016-05-23 10:11                               ` Roger Quadros
@ 2016-05-23 10:34                                 ` Jun Li
  2016-05-23 10:36                                   ` Roger Quadros
  0 siblings, 1 reply; 62+ messages in thread
From: Jun Li @ 2016-05-23 10:34 UTC (permalink / raw)
  To: Roger Quadros, Peter Chen
  Cc: peter.chen, balbi, tony, gregkh, dan.j.williams, mathias.nyman,
	Joao.Pinto, sergei.shtylyov, jun.li, grygorii.strashko,
	yoshihiro.shimoda.uh, robh, nsekhar, b-liu, linux-usb,
	linux-omap, linux-kernel, devicetree

Hi

> -----Original Message-----
> From: Roger Quadros [mailto:rogerq@ti.com]
> Sent: Monday, May 23, 2016 6:12 PM
> To: Peter Chen <hzpeterchen@gmail.com>
> Cc: Jun Li <jun.li@nxp.com>; peter.chen@freescale.com; balbi@kernel.org;
> tony@atomide.com; gregkh@linuxfoundation.org; dan.j.williams@intel.com;
> mathias.nyman@linux.intel.com; Joao.Pinto@synopsys.com;
> sergei.shtylyov@cogentembedded.com; jun.li@freescale.com;
> grygorii.strashko@ti.com; yoshihiro.shimoda.uh@renesas.com;
> robh@kernel.org; nsekhar@ti.com; b-liu@ti.com; linux-usb@vger.kernel.org;
> linux-omap@vger.kernel.org; linux-kernel@vger.kernel.org;
> devicetree@vger.kernel.org
> Subject: Re: [PATCH v8 13/14] usb: gadget: udc: adapt to OTG core
> 
> On 23/05/16 06:21, Peter Chen wrote:
> > On Sat, May 21, 2016 at 10:29:40AM +0800, Peter Chen wrote:
> >> On Thu, May 19, 2016 at 10:32:44AM +0300, Roger Quadros wrote:
> >>> On 18/05/16 17:46, Jun Li wrote:
> >>>>
> >>>>
> >>>>>>>
> >>>>>>> I didn't want to have complex Kconfig so decided to have otg as
> >>>>>>> built-in only.
> >>>>>>> What do you want me to change in existing code? and why?
> >>>>>>
> >>>>>> Remove those stuff which only for pass diff driver config Like
> >>>>>> every controller driver need a duplicated
> >>>>>>
> >>>>>> static struct otg_hcd_ops ci_hcd_ops = {
> >>>>>>     ...
> >>>>>> }
> >>>>>
> >>>>> This is an exception only. Every controller driver doesn't need to
> >>>>> implement hcd_ops. It is implemented in the hcd core.
> >>>>>
> >>>>>>
> >>>>>> And here is another example, for gadget connect, otg driver can
> >>>>>> directly call to usb_udc_vbus_handler() in drd state machine, but
> >>>>>> you create another interface:
> >>>>>>
> >>>>>> .connect_control = usb_gadget_connect_control,
> >>>>>>
> >>>>>> If the symbol is defined in one driver which is 'm', another
> >>>>>> driver reference it should be 'm' as well, then there is no this
> >>>>>> kind of problem as my understanding.
> >>>>>
> >>>>> That is fine as long as all are 'm'. but how do you solve the case
> >>>>> when Gadget is built in and host is 'm'? OTG has to be built-in
> >>>>> and you will need an hcd to gadget interface.
> >>>>
> >>>> Hcd to gadget interface? Or you want to say otg to host interface?
> >>>
> >>> Sorry, I meant to say host to otg interface.
> >>>
> >>>>
> >>>> I think hcd and gadget are independent each other, now
> >>>>
> >>>> Hcd --> otg; and gadget --> otg, (hcd and gadget use otg's symbol)
> >>>
> >>> It is actually a circular dependency for both.
> >>>  hcd <--> otg and gadget <--> otg
> >>>
> >>> hcd -> otg for usb_otg_register/unregister_hcd otg -> hcd for
> >>> usb_add/remove_hcd, usb_bus_start_enum, usb_control_msg,
> >>> usb_hub_find_child
> >>>
> >>> gadget -> otg for usb_otg_register/unregister_gadget
> >>> otg -> gadget for usb_gadget_start/stop, usb_udc_vbus_handler
> >>>
> >>> Now consider what will happen if I get rid of the otg_hcd and
> otg_gadget interfaces.
> >>> 'y' means built-in, 'm' means module.
> >>>
> >>> 1) hcd 'y', gadget 'y'
> >>> otg has to be 'y' for proper build.
> >>>
> >>> 2) hcd 'm', gadget 'm'
> >>> otg has to be 'm' for proper build.
> >>>
> >>> 3) hcd 'y', gadget 'm'
> >>> Build will fail always.
> >>> If otg is 'y', otg build will fail due to dependency on gadget.
> >>> If otg is 'm', hcd build will fail due to dependency on otg.
> >>>
> >>> 4) hcd 'm', gadget 'y'
> >>> Build will fail always.
> >>> If otg is 'y', otg build will fail due to dependency on hcd.
> >>> If otg is 'm', gadget build will fails due to dependency on otg.
> >>>
> >>> So I solve this problem by adding the otg_hcd_ops and otg_gadget_ops
> >>> to remove otg->hcd and otg->gadget dependency.
> >>>
> >>> Now we can address 3) and 4) like so
> >>>
> >>> 3) hcd 'y', gadget 'm'
> >>> otg has to be 'y' for proper build.
> >>>
> >>> 4) hcd 'm', gadget 'y'
> >>> otg has to be 'y' for proper build.
> >>>
> >>
> >> How about this:
> >> Moving usb_otg_register/unregister_hcd to host driver to remove
> >> dependency hcd->otg. And moving usb_otg_get_data to common.c.
> >>
> >> Delete the wait queue at usb-otg.c, and if calling usb_otg_get_data
> >> returns NULL, the host/device driver's probe return -EPROBE_DEFER.
> >> When the otg driver is probed successfully, the host/device will be
> >> re-probed again, and usb_otg_register_hcd will be called again.
> >>
> >> And let OTG depends on HCD && GADGET, and delete otg_hcd_ops and
> >> otg_gadget_ops. Below build dependency issues can be fixed.
> >> What do you think?
> >>
> >>> 1) hcd 'y', gadget 'y'
> >>> otg has to be 'y' for proper build.
> >>>
> >>> 2) hcd 'm', gadget 'm'
> >>> otg has to be 'm' for proper build.
> >>>
> >>> 3) hcd 'y', gadget 'm'
> >>> Build will fail always.
> >>> If otg is 'y', otg build will fail due to dependency on gadget.
> >>> If otg is 'm', hcd build will fail due to dependency on otg.
> >>>
> >>> 4) hcd 'm', gadget 'y'
> >>> Build will fail always.
> >>> If otg is 'y', otg build will fail due to dependency on hcd.
> >>> If otg is 'm', gadget build will fails due to dependency on otg.
> >> --
> >>
> >
> > After thinking more, my suggestion can't work. How about moving
> > CONFIG_USB_OTG out of CONFIG_USB, in that case, CONFIG_USB_OTG can
> > only be built in.
> >
> I tried this but it still doesn't resolve 3 and 4. I.e.
> it can't be automatically set to 'y' when either of hcd/gadget is 'y'
> and the other is 'm'.

USB_OTG only can be selected by *user*, can't be automatically set to
'y' like you said, no matter what's hcd/gadget config, USB_OTG can be
disabled in any cases.

I think Peter's intention is to make USB_OTG to be 'bool', either disabled;
or built-in(if enabled), something like your original idea?

Li Jun

> 
> I think some kconfig trickery can be done to get what we want.
> 
> cheers,
> -roger

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v8 13/14] usb: gadget: udc: adapt to OTG core
  2016-05-23 10:34                                 ` Jun Li
@ 2016-05-23 10:36                                   ` Roger Quadros
  2016-05-24  2:53                                     ` Peter Chen
  0 siblings, 1 reply; 62+ messages in thread
From: Roger Quadros @ 2016-05-23 10:36 UTC (permalink / raw)
  To: Jun Li, Peter Chen
  Cc: peter.chen, balbi, tony, gregkh, dan.j.williams, mathias.nyman,
	Joao.Pinto, sergei.shtylyov, jun.li, grygorii.strashko,
	yoshihiro.shimoda.uh, robh, nsekhar, b-liu, linux-usb,
	linux-omap, linux-kernel, devicetree

On 23/05/16 13:34, Jun Li wrote:
> Hi
> 
>> -----Original Message-----
>> From: Roger Quadros [mailto:rogerq@ti.com]
>> Sent: Monday, May 23, 2016 6:12 PM
>> To: Peter Chen <hzpeterchen@gmail.com>
>> Cc: Jun Li <jun.li@nxp.com>; peter.chen@freescale.com; balbi@kernel.org;
>> tony@atomide.com; gregkh@linuxfoundation.org; dan.j.williams@intel.com;
>> mathias.nyman@linux.intel.com; Joao.Pinto@synopsys.com;
>> sergei.shtylyov@cogentembedded.com; jun.li@freescale.com;
>> grygorii.strashko@ti.com; yoshihiro.shimoda.uh@renesas.com;
>> robh@kernel.org; nsekhar@ti.com; b-liu@ti.com; linux-usb@vger.kernel.org;
>> linux-omap@vger.kernel.org; linux-kernel@vger.kernel.org;
>> devicetree@vger.kernel.org
>> Subject: Re: [PATCH v8 13/14] usb: gadget: udc: adapt to OTG core
>>
>> On 23/05/16 06:21, Peter Chen wrote:
>>> On Sat, May 21, 2016 at 10:29:40AM +0800, Peter Chen wrote:
>>>> On Thu, May 19, 2016 at 10:32:44AM +0300, Roger Quadros wrote:
>>>>> On 18/05/16 17:46, Jun Li wrote:
>>>>>>
>>>>>>
>>>>>>>>>
>>>>>>>>> I didn't want to have complex Kconfig so decided to have otg as
>>>>>>>>> built-in only.
>>>>>>>>> What do you want me to change in existing code? and why?
>>>>>>>>
>>>>>>>> Remove those stuff which only for pass diff driver config Like
>>>>>>>> every controller driver need a duplicated
>>>>>>>>
>>>>>>>> static struct otg_hcd_ops ci_hcd_ops = {
>>>>>>>>     ...
>>>>>>>> }
>>>>>>>
>>>>>>> This is an exception only. Every controller driver doesn't need to
>>>>>>> implement hcd_ops. It is implemented in the hcd core.
>>>>>>>
>>>>>>>>
>>>>>>>> And here is another example, for gadget connect, otg driver can
>>>>>>>> directly call to usb_udc_vbus_handler() in drd state machine, but
>>>>>>>> you create another interface:
>>>>>>>>
>>>>>>>> .connect_control = usb_gadget_connect_control,
>>>>>>>>
>>>>>>>> If the symbol is defined in one driver which is 'm', another
>>>>>>>> driver reference it should be 'm' as well, then there is no this
>>>>>>>> kind of problem as my understanding.
>>>>>>>
>>>>>>> That is fine as long as all are 'm'. but how do you solve the case
>>>>>>> when Gadget is built in and host is 'm'? OTG has to be built-in
>>>>>>> and you will need an hcd to gadget interface.
>>>>>>
>>>>>> Hcd to gadget interface? Or you want to say otg to host interface?
>>>>>
>>>>> Sorry, I meant to say host to otg interface.
>>>>>
>>>>>>
>>>>>> I think hcd and gadget are independent each other, now
>>>>>>
>>>>>> Hcd --> otg; and gadget --> otg, (hcd and gadget use otg's symbol)
>>>>>
>>>>> It is actually a circular dependency for both.
>>>>>  hcd <--> otg and gadget <--> otg
>>>>>
>>>>> hcd -> otg for usb_otg_register/unregister_hcd otg -> hcd for
>>>>> usb_add/remove_hcd, usb_bus_start_enum, usb_control_msg,
>>>>> usb_hub_find_child
>>>>>
>>>>> gadget -> otg for usb_otg_register/unregister_gadget
>>>>> otg -> gadget for usb_gadget_start/stop, usb_udc_vbus_handler
>>>>>
>>>>> Now consider what will happen if I get rid of the otg_hcd and
>> otg_gadget interfaces.
>>>>> 'y' means built-in, 'm' means module.
>>>>>
>>>>> 1) hcd 'y', gadget 'y'
>>>>> otg has to be 'y' for proper build.
>>>>>
>>>>> 2) hcd 'm', gadget 'm'
>>>>> otg has to be 'm' for proper build.
>>>>>
>>>>> 3) hcd 'y', gadget 'm'
>>>>> Build will fail always.
>>>>> If otg is 'y', otg build will fail due to dependency on gadget.
>>>>> If otg is 'm', hcd build will fail due to dependency on otg.
>>>>>
>>>>> 4) hcd 'm', gadget 'y'
>>>>> Build will fail always.
>>>>> If otg is 'y', otg build will fail due to dependency on hcd.
>>>>> If otg is 'm', gadget build will fails due to dependency on otg.
>>>>>
>>>>> So I solve this problem by adding the otg_hcd_ops and otg_gadget_ops
>>>>> to remove otg->hcd and otg->gadget dependency.
>>>>>
>>>>> Now we can address 3) and 4) like so
>>>>>
>>>>> 3) hcd 'y', gadget 'm'
>>>>> otg has to be 'y' for proper build.
>>>>>
>>>>> 4) hcd 'm', gadget 'y'
>>>>> otg has to be 'y' for proper build.
>>>>>
>>>>
>>>> How about this:
>>>> Moving usb_otg_register/unregister_hcd to host driver to remove
>>>> dependency hcd->otg. And moving usb_otg_get_data to common.c.
>>>>
>>>> Delete the wait queue at usb-otg.c, and if calling usb_otg_get_data
>>>> returns NULL, the host/device driver's probe return -EPROBE_DEFER.
>>>> When the otg driver is probed successfully, the host/device will be
>>>> re-probed again, and usb_otg_register_hcd will be called again.
>>>>
>>>> And let OTG depends on HCD && GADGET, and delete otg_hcd_ops and
>>>> otg_gadget_ops. Below build dependency issues can be fixed.
>>>> What do you think?
>>>>
>>>>> 1) hcd 'y', gadget 'y'
>>>>> otg has to be 'y' for proper build.
>>>>>
>>>>> 2) hcd 'm', gadget 'm'
>>>>> otg has to be 'm' for proper build.
>>>>>
>>>>> 3) hcd 'y', gadget 'm'
>>>>> Build will fail always.
>>>>> If otg is 'y', otg build will fail due to dependency on gadget.
>>>>> If otg is 'm', hcd build will fail due to dependency on otg.
>>>>>
>>>>> 4) hcd 'm', gadget 'y'
>>>>> Build will fail always.
>>>>> If otg is 'y', otg build will fail due to dependency on hcd.
>>>>> If otg is 'm', gadget build will fails due to dependency on otg.
>>>> --
>>>>
>>>
>>> After thinking more, my suggestion can't work. How about moving
>>> CONFIG_USB_OTG out of CONFIG_USB, in that case, CONFIG_USB_OTG can
>>> only be built in.
>>>
>> I tried this but it still doesn't resolve 3 and 4. I.e.
>> it can't be automatically set to 'y' when either of hcd/gadget is 'y'
>> and the other is 'm'.
> 
> USB_OTG only can be selected by *user*, can't be automatically set to
> 'y' like you said, no matter what's hcd/gadget config, USB_OTG can be
> disabled in any cases.

Yes. I am on the same page with that.
> 
> I think Peter's intention is to make USB_OTG to be 'bool', either disabled;
> or built-in(if enabled), something like your original idea?

I'm fine with my original idea if you guys can confirm :).

cheers,
-roger
> 
> Li Jun
> 
>>
>> I think some kconfig trickery can be done to get what we want.
>>
>> cheers,
>> -roger

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v9 09/14] usb: of: add an API to get OTG device from USB controller node
  2016-05-20  9:29   ` [PATCH v9 " Roger Quadros
@ 2016-05-23 21:06     ` Rob Herring
  0 siblings, 0 replies; 62+ messages in thread
From: Rob Herring @ 2016-05-23 21:06 UTC (permalink / raw)
  To: Roger Quadros
  Cc: peter.chen, balbi, tony, gregkh, dan.j.williams, mathias.nyman,
	Joao.Pinto, sergei.shtylyov, jun.li, grygorii.strashko,
	yoshihiro.shimoda.uh, nsekhar, b-liu, linux-usb, linux-omap,
	linux-kernel, devicetree

On Fri, May 20, 2016 at 12:29:59PM +0300, Roger Quadros wrote:
> The OTG controller and the USB controller can be linked via the
> 'otg-controller' property in the USB controller's device node.
> 
> of_usb_get_otg() can be used to get the OTG controller device
> from the USB controller's device node.
> 
> Signed-off-by: Roger Quadros <rogerq@ti.com>
> Acked-by: Peter Chen <peter.chen@nxp.com>
> ---
> v9:
> Clearly indicate which properties are for OTG controller and which ones
> are for host/device controllers
> 
>  Documentation/devicetree/bindings/usb/generic.txt |  7 ++++++

Acked-by: Rob Herring <robh@kernel.org>

>  drivers/usb/common/common.c                       | 27 +++++++++++++++++++++++
>  include/linux/usb/of.h                            |  9 ++++++++
>  3 files changed, 43 insertions(+)

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v9 10/14] usb: otg: add hcd companion support
  2016-05-20  9:32   ` [PATCH v9 " Roger Quadros
@ 2016-05-23 21:07     ` Rob Herring
  0 siblings, 0 replies; 62+ messages in thread
From: Rob Herring @ 2016-05-23 21:07 UTC (permalink / raw)
  To: Roger Quadros
  Cc: peter.chen, balbi, tony, gregkh, dan.j.williams, mathias.nyman,
	Joao.Pinto, sergei.shtylyov, jun.li, grygorii.strashko,
	yoshihiro.shimoda.uh, nsekhar, b-liu, linux-usb, linux-omap,
	linux-kernel, devicetree

On Fri, May 20, 2016 at 12:32:27PM +0300, Roger Quadros wrote:
> Since some host controller (e.g. EHCI) needs a companion host controller
> (e.g. OHCI), this patch adds such a configuration to use it in the OTG
> core.
> 
> Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
> Signed-off-by: Roger Quadros <rogerq@ti.com>
> Acked-by: Peter Chen <peter.chen@nxp.com>
> ---
> v9:
> - add DT property documentation under OTG controllers.
> 
>  Documentation/devicetree/bindings/usb/generic.txt |  3 +++

Acked-by: Rob Herring <robh@kernel.org>

>  drivers/usb/common/usb-otg.c                      | 32 ++++++++++++++++-------
>  include/linux/usb/otg.h                           |  7 ++++-
>  3 files changed, 32 insertions(+), 10 deletions(-)

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v8 13/14] usb: gadget: udc: adapt to OTG core
  2016-05-23 10:36                                   ` Roger Quadros
@ 2016-05-24  2:53                                     ` Peter Chen
  2016-06-08  7:32                                       ` Roger Quadros
  0 siblings, 1 reply; 62+ messages in thread
From: Peter Chen @ 2016-05-24  2:53 UTC (permalink / raw)
  To: Roger Quadros
  Cc: Jun Li, peter.chen, balbi, tony, gregkh, dan.j.williams,
	mathias.nyman, Joao.Pinto, sergei.shtylyov, jun.li,
	grygorii.strashko, yoshihiro.shimoda.uh, robh, nsekhar, b-liu,
	linux-usb, linux-omap, linux-kernel, devicetree

On Mon, May 23, 2016 at 01:36:51PM +0300, Roger Quadros wrote:
> On 23/05/16 13:34, Jun Li wrote:
> > Hi
> > 
> >> -----Original Message-----
> >> From: Roger Quadros [mailto:rogerq@ti.com]
> >> Sent: Monday, May 23, 2016 6:12 PM
> >> To: Peter Chen <hzpeterchen@gmail.com>
> >> Cc: Jun Li <jun.li@nxp.com>; peter.chen@freescale.com; balbi@kernel.org;
> >> tony@atomide.com; gregkh@linuxfoundation.org; dan.j.williams@intel.com;
> >> mathias.nyman@linux.intel.com; Joao.Pinto@synopsys.com;
> >> sergei.shtylyov@cogentembedded.com; jun.li@freescale.com;
> >> grygorii.strashko@ti.com; yoshihiro.shimoda.uh@renesas.com;
> >> robh@kernel.org; nsekhar@ti.com; b-liu@ti.com; linux-usb@vger.kernel.org;
> >> linux-omap@vger.kernel.org; linux-kernel@vger.kernel.org;
> >> devicetree@vger.kernel.org
> >> Subject: Re: [PATCH v8 13/14] usb: gadget: udc: adapt to OTG core
> >>
> >> On 23/05/16 06:21, Peter Chen wrote:
> >>> On Sat, May 21, 2016 at 10:29:40AM +0800, Peter Chen wrote:
> >>>> On Thu, May 19, 2016 at 10:32:44AM +0300, Roger Quadros wrote:
> >>>>> On 18/05/16 17:46, Jun Li wrote:
> >>>>>>
> >>>>>>
> >>>>>>>>>
> >>>>>>>>> I didn't want to have complex Kconfig so decided to have otg as
> >>>>>>>>> built-in only.
> >>>>>>>>> What do you want me to change in existing code? and why?
> >>>>>>>>
> >>>>>>>> Remove those stuff which only for pass diff driver config Like
> >>>>>>>> every controller driver need a duplicated
> >>>>>>>>
> >>>>>>>> static struct otg_hcd_ops ci_hcd_ops = {
> >>>>>>>>     ...
> >>>>>>>> }
> >>>>>>>
> >>>>>>> This is an exception only. Every controller driver doesn't need to
> >>>>>>> implement hcd_ops. It is implemented in the hcd core.
> >>>>>>>
> >>>>>>>>
> >>>>>>>> And here is another example, for gadget connect, otg driver can
> >>>>>>>> directly call to usb_udc_vbus_handler() in drd state machine, but
> >>>>>>>> you create another interface:
> >>>>>>>>
> >>>>>>>> .connect_control = usb_gadget_connect_control,
> >>>>>>>>
> >>>>>>>> If the symbol is defined in one driver which is 'm', another
> >>>>>>>> driver reference it should be 'm' as well, then there is no this
> >>>>>>>> kind of problem as my understanding.
> >>>>>>>
> >>>>>>> That is fine as long as all are 'm'. but how do you solve the case
> >>>>>>> when Gadget is built in and host is 'm'? OTG has to be built-in
> >>>>>>> and you will need an hcd to gadget interface.
> >>>>>>
> >>>>>> Hcd to gadget interface? Or you want to say otg to host interface?
> >>>>>
> >>>>> Sorry, I meant to say host to otg interface.
> >>>>>
> >>>>>>
> >>>>>> I think hcd and gadget are independent each other, now
> >>>>>>
> >>>>>> Hcd --> otg; and gadget --> otg, (hcd and gadget use otg's symbol)
> >>>>>
> >>>>> It is actually a circular dependency for both.
> >>>>>  hcd <--> otg and gadget <--> otg
> >>>>>
> >>>>> hcd -> otg for usb_otg_register/unregister_hcd otg -> hcd for
> >>>>> usb_add/remove_hcd, usb_bus_start_enum, usb_control_msg,
> >>>>> usb_hub_find_child
> >>>>>
> >>>>> gadget -> otg for usb_otg_register/unregister_gadget
> >>>>> otg -> gadget for usb_gadget_start/stop, usb_udc_vbus_handler
> >>>>>
> >>>>> Now consider what will happen if I get rid of the otg_hcd and
> >> otg_gadget interfaces.
> >>>>> 'y' means built-in, 'm' means module.
> >>>>>
> >>>>> 1) hcd 'y', gadget 'y'
> >>>>> otg has to be 'y' for proper build.
> >>>>>
> >>>>> 2) hcd 'm', gadget 'm'
> >>>>> otg has to be 'm' for proper build.
> >>>>>
> >>>>> 3) hcd 'y', gadget 'm'
> >>>>> Build will fail always.
> >>>>> If otg is 'y', otg build will fail due to dependency on gadget.
> >>>>> If otg is 'm', hcd build will fail due to dependency on otg.
> >>>>>
> >>>>> 4) hcd 'm', gadget 'y'
> >>>>> Build will fail always.
> >>>>> If otg is 'y', otg build will fail due to dependency on hcd.
> >>>>> If otg is 'm', gadget build will fails due to dependency on otg.
> >>>>>
> >>>>> So I solve this problem by adding the otg_hcd_ops and otg_gadget_ops
> >>>>> to remove otg->hcd and otg->gadget dependency.
> >>>>>
> >>>>> Now we can address 3) and 4) like so
> >>>>>
> >>>>> 3) hcd 'y', gadget 'm'
> >>>>> otg has to be 'y' for proper build.
> >>>>>
> >>>>> 4) hcd 'm', gadget 'y'
> >>>>> otg has to be 'y' for proper build.
> >>>>>
> >>>>
> >>>> How about this:
> >>>> Moving usb_otg_register/unregister_hcd to host driver to remove
> >>>> dependency hcd->otg. And moving usb_otg_get_data to common.c.
> >>>>
> >>>> Delete the wait queue at usb-otg.c, and if calling usb_otg_get_data
> >>>> returns NULL, the host/device driver's probe return -EPROBE_DEFER.
> >>>> When the otg driver is probed successfully, the host/device will be
> >>>> re-probed again, and usb_otg_register_hcd will be called again.
> >>>>
> >>>> And let OTG depends on HCD && GADGET, and delete otg_hcd_ops and
> >>>> otg_gadget_ops. Below build dependency issues can be fixed.
> >>>> What do you think?
> >>>>
> >>>>> 1) hcd 'y', gadget 'y'
> >>>>> otg has to be 'y' for proper build.
> >>>>>
> >>>>> 2) hcd 'm', gadget 'm'
> >>>>> otg has to be 'm' for proper build.
> >>>>>
> >>>>> 3) hcd 'y', gadget 'm'
> >>>>> Build will fail always.
> >>>>> If otg is 'y', otg build will fail due to dependency on gadget.
> >>>>> If otg is 'm', hcd build will fail due to dependency on otg.
> >>>>>
> >>>>> 4) hcd 'm', gadget 'y'
> >>>>> Build will fail always.
> >>>>> If otg is 'y', otg build will fail due to dependency on hcd.
> >>>>> If otg is 'm', gadget build will fails due to dependency on otg.
> >>>> --
> >>>>
> >>>
> >>> After thinking more, my suggestion can't work. How about moving
> >>> CONFIG_USB_OTG out of CONFIG_USB, in that case, CONFIG_USB_OTG can
> >>> only be built in.
> >>>
> >> I tried this but it still doesn't resolve 3 and 4. I.e.
> >> it can't be automatically set to 'y' when either of hcd/gadget is 'y'
> >> and the other is 'm'.
> > 
> > USB_OTG only can be selected by *user*, can't be automatically set to
> > 'y' like you said, no matter what's hcd/gadget config, USB_OTG can be
> > disabled in any cases.
> 
> Yes. I am on the same page with that.
> > 
> > I think Peter's intention is to make USB_OTG to be 'bool', either disabled;
> > or built-in(if enabled), something like your original idea?
> 
> I'm fine with my original idea if you guys can confirm :).
> 

Please do it.

-- 

Best Regards,
Peter Chen

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v8 08/14] usb: otg: add OTG/dual-role core
  2016-05-13 10:03 ` [PATCH v8 08/14] usb: otg: add OTG/dual-role core Roger Quadros
  2016-05-16  9:00   ` Roger Quadros
@ 2016-05-24  9:45   ` Roger Quadros
  2016-05-25  2:44     ` Peter Chen
  1 sibling, 1 reply; 62+ messages in thread
From: Roger Quadros @ 2016-05-24  9:45 UTC (permalink / raw)
  To: peter.chen
  Cc: balbi, tony, gregkh, dan.j.williams, mathias.nyman, Joao.Pinto,
	sergei.shtylyov, jun.li, grygorii.strashko, yoshihiro.shimoda.uh,
	robh, nsekhar, b-liu, linux-usb, linux-omap, linux-kernel,
	devicetree

Hi Peter,

I have one question here. Please see below.

On 13/05/16 13:03, Roger Quadros wrote:
> It provides APIs for the following tasks
> 
> - Registering an OTG/dual-role capable controller
> - Registering Host and Gadget controllers to OTG core
> - Providing inputs to and kicking the OTG state machine
> 
> Provide a dual-role device (DRD) state machine.
> DRD mode is a reduced functionality OTG mode. In this mode
> we don't support SRP, HNP and dynamic role-swap.
> 
> In DRD operation, the controller mode (Host or Peripheral)
> is decided based on the ID pin status. Once a cable plug (Type-A
> or Type-B) is attached the controller selects the state
> and doesn't change till the cable in unplugged and a different
> cable type is inserted.
> 
> As we don't need most of the complex OTG states and OTG timers
> we implement a lean DRD state machine in usb-otg.c.
> The DRD state machine is only interested in 2 hardware inputs
> 'id' and 'b_sess_vld'.
> 
> Signed-off-by: Roger Quadros <rogerq@ti.com>
> ---
>  drivers/usb/common/Makefile  |    2 +-
>  drivers/usb/common/usb-otg.c | 1042 ++++++++++++++++++++++++++++++++++++++++++
>  drivers/usb/core/Kconfig     |    4 +-
>  include/linux/usb/gadget.h   |    2 +
>  include/linux/usb/hcd.h      |    1 +
>  include/linux/usb/otg-fsm.h  |    7 +
>  include/linux/usb/otg.h      |  154 ++++++-
>  7 files changed, 1206 insertions(+), 6 deletions(-)
>  create mode 100644 drivers/usb/common/usb-otg.c
> 

<snip>

> +
> +/**
> + * usb_otg_register() - Register the OTG/dual-role device to OTG core
> + * @dev: OTG/dual-role controller device.
> + * @config: OTG configuration.
> + *
> + * Registers the OTG/dual-role controller device with the USB OTG core.
> + *
> + * Return: struct usb_otg * if success, ERR_PTR() if error.
> + */
> +struct usb_otg *usb_otg_register(struct device *dev,
> +				 struct usb_otg_config *config)
> +{
> +	struct usb_otg *otg;
> +	struct otg_wait_data *wait;
> +	int ret = 0;
> +
> +	if (!dev || !config || !config->fsm_ops)
> +		return ERR_PTR(-EINVAL);
> +
> +	/* already in list? */
> +	mutex_lock(&otg_list_mutex);
> +	if (usb_otg_get_data(dev)) {
> +		dev_err(dev, "otg: %s: device already in otg list\n",
> +			__func__);
> +		ret = -EINVAL;
> +		goto unlock;
> +	}
> +
> +	/* allocate and add to list */
> +	otg = kzalloc(sizeof(*otg), GFP_KERNEL);
> +	if (!otg) {
> +		ret = -ENOMEM;
> +		goto unlock;
> +	}
> +
> +	otg->dev = dev;
> +	otg->caps = config->otg_caps;

Here, we should be checking if user needs to disable any OTG features. So,

	if (dev->of_node)
		of_usb_update_otg_caps(dev->of_node, &otg->caps);

Do you agree?
This means we need to change otg->caps from 'struct usb_otg_caps *caps;'
to 'struct usb_otg_caps caps;' so that we can modify the local copy instead
of the one passed by the OTG controller.

We can also move of_usb_update_otg_caps() to otg.h.

We will also need to modify the udc-core code so that it sets gadget->otg_caps
to the modified otg_caps from the OTG core. This will ensure that the right
OTG descriptors are sent.

So we will have to introduce an API.

struct usb_otg_caps *usb_otg_get_otg_caps(struct device *otg_dev)

And in udc-core.c,

static int udc_bind_to_driver(struct usb_udc *udc, struct usb_gadget_driver *driver)
{
..
        ret = driver->bind(udc->gadget, driver);
        if (ret)
                goto err1;

        /* If OTG, the otg core starts the UDC when needed */
        if (udc->gadget->otg_dev) {
+		udc->gadget->is_otg = true;
+		udc->gadget->otg_caps = usb_otg_get_otg_caps(udc->gadget->otg_dev);
                mutex_unlock(&udc_lock);
                usb_otg_register_gadget(udc->gadget, &otg_gadget_intf);
                mutex_lock(&udc_lock);
        } else {
                ret = usb_gadget_udc_start(udc);
                if (ret) {
                        driver->unbind(udc->gadget);
                        goto err1;
                }
                usb_udc_connect_control(udc);
        }
..
}

What do you say?

regards,
-roger

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v8 08/14] usb: otg: add OTG/dual-role core
  2016-05-24  9:45   ` Roger Quadros
@ 2016-05-25  2:44     ` Peter Chen
  2016-05-25  3:19       ` Jun Li
  2016-05-25 12:21       ` Roger Quadros
  0 siblings, 2 replies; 62+ messages in thread
From: Peter Chen @ 2016-05-25  2:44 UTC (permalink / raw)
  To: Roger Quadros
  Cc: peter.chen, balbi, tony, gregkh, dan.j.williams, mathias.nyman,
	Joao.Pinto, sergei.shtylyov, jun.li, grygorii.strashko,
	yoshihiro.shimoda.uh, robh, nsekhar, b-liu, linux-usb,
	linux-omap, linux-kernel, devicetree

On Tue, May 24, 2016 at 12:45:46PM +0300, Roger Quadros wrote:
> Hi Peter,
> 
> I have one question here. Please see below.
> 
> On 13/05/16 13:03, Roger Quadros wrote:
> > It provides APIs for the following tasks
> > 
> > - Registering an OTG/dual-role capable controller
> > - Registering Host and Gadget controllers to OTG core
> > - Providing inputs to and kicking the OTG state machine
> > 
> > Provide a dual-role device (DRD) state machine.
> > DRD mode is a reduced functionality OTG mode. In this mode
> > we don't support SRP, HNP and dynamic role-swap.
> > 
> > In DRD operation, the controller mode (Host or Peripheral)
> > is decided based on the ID pin status. Once a cable plug (Type-A
> > or Type-B) is attached the controller selects the state
> > and doesn't change till the cable in unplugged and a different
> > cable type is inserted.
> > 
> > As we don't need most of the complex OTG states and OTG timers
> > we implement a lean DRD state machine in usb-otg.c.
> > The DRD state machine is only interested in 2 hardware inputs
> > 'id' and 'b_sess_vld'.
> > 
> > Signed-off-by: Roger Quadros <rogerq@ti.com>
> > ---
> >  drivers/usb/common/Makefile  |    2 +-
> >  drivers/usb/common/usb-otg.c | 1042 ++++++++++++++++++++++++++++++++++++++++++
> >  drivers/usb/core/Kconfig     |    4 +-
> >  include/linux/usb/gadget.h   |    2 +
> >  include/linux/usb/hcd.h      |    1 +
> >  include/linux/usb/otg-fsm.h  |    7 +
> >  include/linux/usb/otg.h      |  154 ++++++-
> >  7 files changed, 1206 insertions(+), 6 deletions(-)
> >  create mode 100644 drivers/usb/common/usb-otg.c
> > 
> 
> <snip>
> 
> > +
> > +/**
> > + * usb_otg_register() - Register the OTG/dual-role device to OTG core
> > + * @dev: OTG/dual-role controller device.
> > + * @config: OTG configuration.
> > + *
> > + * Registers the OTG/dual-role controller device with the USB OTG core.
> > + *
> > + * Return: struct usb_otg * if success, ERR_PTR() if error.
> > + */
> > +struct usb_otg *usb_otg_register(struct device *dev,
> > +				 struct usb_otg_config *config)
> > +{
> > +	struct usb_otg *otg;
> > +	struct otg_wait_data *wait;
> > +	int ret = 0;
> > +
> > +	if (!dev || !config || !config->fsm_ops)
> > +		return ERR_PTR(-EINVAL);
> > +
> > +	/* already in list? */
> > +	mutex_lock(&otg_list_mutex);
> > +	if (usb_otg_get_data(dev)) {
> > +		dev_err(dev, "otg: %s: device already in otg list\n",
> > +			__func__);
> > +		ret = -EINVAL;
> > +		goto unlock;
> > +	}
> > +
> > +	/* allocate and add to list */
> > +	otg = kzalloc(sizeof(*otg), GFP_KERNEL);
> > +	if (!otg) {
> > +		ret = -ENOMEM;
> > +		goto unlock;
> > +	}
> > +
> > +	otg->dev = dev;
> > +	otg->caps = config->otg_caps;
> 
> Here, we should be checking if user needs to disable any OTG features. So,
> 
> 	if (dev->of_node)
> 		of_usb_update_otg_caps(dev->of_node, &otg->caps);
> 
> Do you agree?
> This means we need to change otg->caps from 'struct usb_otg_caps *caps;'
> to 'struct usb_otg_caps caps;' so that we can modify the local copy instead
> of the one passed by the OTG controller.

Why can't modify the one from OTG controller directly?

> 
> We can also move of_usb_update_otg_caps() to otg.h.
> 
> We will also need to modify the udc-core code so that it sets gadget->otg_caps
> to the modified otg_caps from the OTG core. This will ensure that the right
> OTG descriptors are sent.
> 
> So we will have to introduce an API.
> 
> struct usb_otg_caps *usb_otg_get_otg_caps(struct device *otg_dev)
> 
> And in udc-core.c,
> 
> static int udc_bind_to_driver(struct usb_udc *udc, struct usb_gadget_driver *driver)
> {
> ..
>         ret = driver->bind(udc->gadget, driver);
>         if (ret)
>                 goto err1;
> 
>         /* If OTG, the otg core starts the UDC when needed */
>         if (udc->gadget->otg_dev) {
> +		udc->gadget->is_otg = true;

gadget->is_otg is only set to true if fully OTG is supported and it
needs to send OTG descriptors at this case. DRD devices should not send OTG
descriptors.

> +		udc->gadget->otg_caps = usb_otg_get_otg_caps(udc->gadget->otg_dev);

Getting otg capabilities should be prior to driver->bind since
usb_otg_descriptor_init is called at that. Besides, Gadget driver
may be probed before otg driver is registered

I am wonder if we can implement defer probe for gadget/udc/host driver
if otg driver is not probed, in that case, some designs can be simpler
like wait list in otg driver.

>                 mutex_unlock(&udc_lock);
>                 usb_otg_register_gadget(udc->gadget, &otg_gadget_intf);
>                 mutex_lock(&udc_lock);
>         } else {
>                 ret = usb_gadget_udc_start(udc);
>                 if (ret) {
>                         driver->unbind(udc->gadget);
>                         goto err1;
>                 }
>                 usb_udc_connect_control(udc);
>         }
> ..
> }
> 
> What do you say?
> 
> regards,
> -roger
> --
> To unsubscribe from this list: send the line "unsubscribe linux-usb" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

-- 

Best Regards,
Peter Chen

^ permalink raw reply	[flat|nested] 62+ messages in thread

* RE: [PATCH v8 08/14] usb: otg: add OTG/dual-role core
  2016-05-25  2:44     ` Peter Chen
@ 2016-05-25  3:19       ` Jun Li
  2016-05-25 12:26         ` Roger Quadros
  2016-05-25 12:21       ` Roger Quadros
  1 sibling, 1 reply; 62+ messages in thread
From: Jun Li @ 2016-05-25  3:19 UTC (permalink / raw)
  To: Peter Chen, Roger Quadros
  Cc: peter.chen, balbi, tony, gregkh, dan.j.williams, mathias.nyman,
	Joao.Pinto, sergei.shtylyov, jun.li, grygorii.strashko,
	yoshihiro.shimoda.uh, robh, nsekhar, b-liu, linux-usb,
	linux-omap, linux-kernel, devicetree



> -----Original Message-----
> From: Peter Chen [mailto:hzpeterchen@gmail.com]
> Sent: Wednesday, May 25, 2016 10:44 AM
> To: Roger Quadros <rogerq@ti.com>
> Cc: peter.chen@freescale.com; balbi@kernel.org; tony@atomide.com;
> gregkh@linuxfoundation.org; dan.j.williams@intel.com;
> mathias.nyman@linux.intel.com; Joao.Pinto@synopsys.com;
> sergei.shtylyov@cogentembedded.com; jun.li@freescale.com;
> grygorii.strashko@ti.com; yoshihiro.shimoda.uh@renesas.com;
> robh@kernel.org; nsekhar@ti.com; b-liu@ti.com; linux-usb@vger.kernel.org;
> linux-omap@vger.kernel.org; linux-kernel@vger.kernel.org;
> devicetree@vger.kernel.org
> Subject: Re: [PATCH v8 08/14] usb: otg: add OTG/dual-role core
> 
> On Tue, May 24, 2016 at 12:45:46PM +0300, Roger Quadros wrote:
> > Hi Peter,
> >
> > I have one question here. Please see below.
> >
> > On 13/05/16 13:03, Roger Quadros wrote:
> > > It provides APIs for the following tasks
> > >
> > > - Registering an OTG/dual-role capable controller
> > > - Registering Host and Gadget controllers to OTG core
> > > - Providing inputs to and kicking the OTG state machine
> > >
> > > Provide a dual-role device (DRD) state machine.
> > > DRD mode is a reduced functionality OTG mode. In this mode we don't
> > > support SRP, HNP and dynamic role-swap.
> > >
> > > In DRD operation, the controller mode (Host or Peripheral) is
> > > decided based on the ID pin status. Once a cable plug (Type-A or
> > > Type-B) is attached the controller selects the state and doesn't
> > > change till the cable in unplugged and a different cable type is
> > > inserted.
> > >
> > > As we don't need most of the complex OTG states and OTG timers we
> > > implement a lean DRD state machine in usb-otg.c.
> > > The DRD state machine is only interested in 2 hardware inputs 'id'
> > > and 'b_sess_vld'.
> > >
> > > Signed-off-by: Roger Quadros <rogerq@ti.com>
> > > ---
> > >  drivers/usb/common/Makefile  |    2 +-
> > >  drivers/usb/common/usb-otg.c | 1042
> ++++++++++++++++++++++++++++++++++++++++++
> > >  drivers/usb/core/Kconfig     |    4 +-
> > >  include/linux/usb/gadget.h   |    2 +
> > >  include/linux/usb/hcd.h      |    1 +
> > >  include/linux/usb/otg-fsm.h  |    7 +
> > >  include/linux/usb/otg.h      |  154 ++++++-
> > >  7 files changed, 1206 insertions(+), 6 deletions(-)  create mode
> > > 100644 drivers/usb/common/usb-otg.c
> > >
> >
> > <snip>
> >
> > > +
> > > +/**
> > > + * usb_otg_register() - Register the OTG/dual-role device to OTG
> > > +core
> > > + * @dev: OTG/dual-role controller device.
> > > + * @config: OTG configuration.
> > > + *
> > > + * Registers the OTG/dual-role controller device with the USB OTG
> core.
> > > + *
> > > + * Return: struct usb_otg * if success, ERR_PTR() if error.
> > > + */
> > > +struct usb_otg *usb_otg_register(struct device *dev,
> > > +				 struct usb_otg_config *config) {
> > > +	struct usb_otg *otg;
> > > +	struct otg_wait_data *wait;
> > > +	int ret = 0;
> > > +
> > > +	if (!dev || !config || !config->fsm_ops)
> > > +		return ERR_PTR(-EINVAL);
> > > +
> > > +	/* already in list? */
> > > +	mutex_lock(&otg_list_mutex);
> > > +	if (usb_otg_get_data(dev)) {
> > > +		dev_err(dev, "otg: %s: device already in otg list\n",
> > > +			__func__);
> > > +		ret = -EINVAL;
> > > +		goto unlock;
> > > +	}
> > > +
> > > +	/* allocate and add to list */
> > > +	otg = kzalloc(sizeof(*otg), GFP_KERNEL);
> > > +	if (!otg) {
> > > +		ret = -ENOMEM;
> > > +		goto unlock;
> > > +	}
> > > +
> > > +	otg->dev = dev;
> > > +	otg->caps = config->otg_caps;
> >
> > Here, we should be checking if user needs to disable any OTG features.
> > So,
> >
> > 	if (dev->of_node)
> > 		of_usb_update_otg_caps(dev->of_node, &otg->caps);
> >
> > Do you agree?
> > This means we need to change otg->caps from 'struct usb_otg_caps *caps;'
> > to 'struct usb_otg_caps caps;' so that we can modify the local copy
> > instead of the one passed by the OTG controller.
> 
> Why can't modify the one from OTG controller directly?

Yes, if user wants to disable any OTG features, this should have been
done in 'config->otg_caps', if not, 'config->otg_caps' from controller
driver is invalid and making no sense.

> 
> >
> > We can also move of_usb_update_otg_caps() to otg.h.
> >
> > We will also need to modify the udc-core code so that it sets
> > gadget->otg_caps to the modified otg_caps from the OTG core. This will
> > ensure that the right OTG descriptors are sent.
> >
> > So we will have to introduce an API.
> >
> > struct usb_otg_caps *usb_otg_get_otg_caps(struct device *otg_dev)
> >
> > And in udc-core.c,
> >
> > static int udc_bind_to_driver(struct usb_udc *udc, struct
> > usb_gadget_driver *driver) { ..
> >         ret = driver->bind(udc->gadget, driver);
> >         if (ret)
> >                 goto err1;
> >
> >         /* If OTG, the otg core starts the UDC when needed */
> >         if (udc->gadget->otg_dev) {
> > +		udc->gadget->is_otg = true;
> 
> gadget->is_otg is only set to true if fully OTG is supported and it
> needs to send OTG descriptors at this case. DRD devices should not send
> OTG descriptors.
> 
> > +		udc->gadget->otg_caps = usb_otg_get_otg_caps(udc->gadget-
> >otg_dev);
> 
> Getting otg capabilities should be prior to driver->bind since
> usb_otg_descriptor_init is called at that. Besides, Gadget driver may be
> probed before otg driver is registered
> 
> I am wonder if we can implement defer probe for gadget/udc/host driver if
> otg driver is not probed, in that case, some designs can be simpler like
> wait list in otg driver.

I even don't see much benefit of this kind of random order of OTG/HCD/GADGET
registration, anyway OTG register can be done firstly.
HCD and GADGET are both separated drivers, but OTG is newly added
and what we need is just a registration in controller driver.
  
> 
> >                 mutex_unlock(&udc_lock);
> >                 usb_otg_register_gadget(udc->gadget, &otg_gadget_intf);
> >                 mutex_lock(&udc_lock);
> >         } else {
> >                 ret = usb_gadget_udc_start(udc);
> >                 if (ret) {
> >                         driver->unbind(udc->gadget);
> >                         goto err1;
> >                 }
> >                 usb_udc_connect_control(udc);
> >         }
> > ..
> > }
> >
> > What do you say?
> >
> > regards,
> > -roger
> > --
> > To unsubscribe from this list: send the line "unsubscribe linux-usb"
> > in the body of a message to majordomo@vger.kernel.org More majordomo
> > info at  http://vger.kernel.org/majordomo-info.html
> 
> --
> 
> Best Regards,
> Peter Chen

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v8 08/14] usb: otg: add OTG/dual-role core
  2016-05-25  2:44     ` Peter Chen
  2016-05-25  3:19       ` Jun Li
@ 2016-05-25 12:21       ` Roger Quadros
  2016-05-25 14:44         ` Jun Li
  1 sibling, 1 reply; 62+ messages in thread
From: Roger Quadros @ 2016-05-25 12:21 UTC (permalink / raw)
  To: Peter Chen
  Cc: peter.chen, balbi, tony, gregkh, dan.j.williams, mathias.nyman,
	Joao.Pinto, sergei.shtylyov, jun.li, grygorii.strashko,
	yoshihiro.shimoda.uh, robh, nsekhar, b-liu, linux-usb,
	linux-omap, linux-kernel, devicetree

On 25/05/16 05:44, Peter Chen wrote:
> On Tue, May 24, 2016 at 12:45:46PM +0300, Roger Quadros wrote:
>> Hi Peter,
>>
>> I have one question here. Please see below.
>>
>> On 13/05/16 13:03, Roger Quadros wrote:
>>> It provides APIs for the following tasks
>>>
>>> - Registering an OTG/dual-role capable controller
>>> - Registering Host and Gadget controllers to OTG core
>>> - Providing inputs to and kicking the OTG state machine
>>>
>>> Provide a dual-role device (DRD) state machine.
>>> DRD mode is a reduced functionality OTG mode. In this mode
>>> we don't support SRP, HNP and dynamic role-swap.
>>>
>>> In DRD operation, the controller mode (Host or Peripheral)
>>> is decided based on the ID pin status. Once a cable plug (Type-A
>>> or Type-B) is attached the controller selects the state
>>> and doesn't change till the cable in unplugged and a different
>>> cable type is inserted.
>>>
>>> As we don't need most of the complex OTG states and OTG timers
>>> we implement a lean DRD state machine in usb-otg.c.
>>> The DRD state machine is only interested in 2 hardware inputs
>>> 'id' and 'b_sess_vld'.
>>>
>>> Signed-off-by: Roger Quadros <rogerq@ti.com>
>>> ---
>>>  drivers/usb/common/Makefile  |    2 +-
>>>  drivers/usb/common/usb-otg.c | 1042 ++++++++++++++++++++++++++++++++++++++++++
>>>  drivers/usb/core/Kconfig     |    4 +-
>>>  include/linux/usb/gadget.h   |    2 +
>>>  include/linux/usb/hcd.h      |    1 +
>>>  include/linux/usb/otg-fsm.h  |    7 +
>>>  include/linux/usb/otg.h      |  154 ++++++-
>>>  7 files changed, 1206 insertions(+), 6 deletions(-)
>>>  create mode 100644 drivers/usb/common/usb-otg.c
>>>
>>
>> <snip>
>>
>>> +
>>> +/**
>>> + * usb_otg_register() - Register the OTG/dual-role device to OTG core
>>> + * @dev: OTG/dual-role controller device.
>>> + * @config: OTG configuration.
>>> + *
>>> + * Registers the OTG/dual-role controller device with the USB OTG core.
>>> + *
>>> + * Return: struct usb_otg * if success, ERR_PTR() if error.
>>> + */
>>> +struct usb_otg *usb_otg_register(struct device *dev,
>>> +				 struct usb_otg_config *config)
>>> +{
>>> +	struct usb_otg *otg;
>>> +	struct otg_wait_data *wait;
>>> +	int ret = 0;
>>> +
>>> +	if (!dev || !config || !config->fsm_ops)
>>> +		return ERR_PTR(-EINVAL);
>>> +
>>> +	/* already in list? */
>>> +	mutex_lock(&otg_list_mutex);
>>> +	if (usb_otg_get_data(dev)) {
>>> +		dev_err(dev, "otg: %s: device already in otg list\n",
>>> +			__func__);
>>> +		ret = -EINVAL;
>>> +		goto unlock;
>>> +	}
>>> +
>>> +	/* allocate and add to list */
>>> +	otg = kzalloc(sizeof(*otg), GFP_KERNEL);
>>> +	if (!otg) {
>>> +		ret = -ENOMEM;
>>> +		goto unlock;
>>> +	}
>>> +
>>> +	otg->dev = dev;
>>> +	otg->caps = config->otg_caps;
>>
>> Here, we should be checking if user needs to disable any OTG features. So,
>>
>> 	if (dev->of_node)
>> 		of_usb_update_otg_caps(dev->of_node, &otg->caps);
>>
>> Do you agree?
>> This means we need to change otg->caps from 'struct usb_otg_caps *caps;'
>> to 'struct usb_otg_caps caps;' so that we can modify the local copy instead
>> of the one passed by the OTG controller.
> 
> Why can't modify the one from OTG controller directly?
> 

There are 2 things.
1) OTG features supported by hardware. This is the controller's config->otg_caps
2) OTG features needed by system designer. This can be a subset of (1).
This needs to be maintained in the OTG core, based on config->otg_caps and
device tree disable flags.

So we can't use OTG controller config->otg_caps directly.

>>
>> We can also move of_usb_update_otg_caps() to otg.h.
>>
>> We will also need to modify the udc-core code so that it sets gadget->otg_caps
>> to the modified otg_caps from the OTG core. This will ensure that the right
>> OTG descriptors are sent.
>>
>> So we will have to introduce an API.
>>
>> struct usb_otg_caps *usb_otg_get_otg_caps(struct device *otg_dev)
>>
>> And in udc-core.c,
>>
>> static int udc_bind_to_driver(struct usb_udc *udc, struct usb_gadget_driver *driver)
>> {
>> ..
>>         ret = driver->bind(udc->gadget, driver);
>>         if (ret)
>>                 goto err1;
>>
>>         /* If OTG, the otg core starts the UDC when needed */
>>         if (udc->gadget->otg_dev) {
>> +		udc->gadget->is_otg = true;
> 
> gadget->is_otg is only set to true if fully OTG is supported and it
> needs to send OTG descriptors at this case. DRD devices should not send OTG
> descriptors.

Agreed.

> 
>> +		udc->gadget->otg_caps = usb_otg_get_otg_caps(udc->gadget->otg_dev);
> 
> Getting otg capabilities should be prior to driver->bind since
> usb_otg_descriptor_init is called at that. Besides, Gadget driver

Correct.

> may be probed before otg driver is registered

udc_bind_to_driver gets called only when both, udc driver and function driver
are available. Defer probing will have to be done in usb_add_gadget_udc_release().

> 
> I am wonder if we can implement defer probe for gadget/udc/host driver
> if otg driver is not probed, in that case, some designs can be simpler
> like wait list in otg driver.

Agree with you on that. Should I work on implementing -EPROBE_DEFER for
hcd.c and udc-core.c if hcd/udc is meant for otg and OTG controller is not
yet probed?

--
cheers,
-roger

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v8 08/14] usb: otg: add OTG/dual-role core
  2016-05-25  3:19       ` Jun Li
@ 2016-05-25 12:26         ` Roger Quadros
  0 siblings, 0 replies; 62+ messages in thread
From: Roger Quadros @ 2016-05-25 12:26 UTC (permalink / raw)
  To: Jun Li, Peter Chen
  Cc: peter.chen, balbi, tony, gregkh, dan.j.williams, mathias.nyman,
	Joao.Pinto, sergei.shtylyov, jun.li, grygorii.strashko,
	yoshihiro.shimoda.uh, robh, nsekhar, b-liu, linux-usb,
	linux-omap, linux-kernel, devicetree

On 25/05/16 06:19, Jun Li wrote:
> 
> 
>> -----Original Message-----
>> From: Peter Chen [mailto:hzpeterchen@gmail.com]
>> Sent: Wednesday, May 25, 2016 10:44 AM
>> To: Roger Quadros <rogerq@ti.com>
>> Cc: peter.chen@freescale.com; balbi@kernel.org; tony@atomide.com;
>> gregkh@linuxfoundation.org; dan.j.williams@intel.com;
>> mathias.nyman@linux.intel.com; Joao.Pinto@synopsys.com;
>> sergei.shtylyov@cogentembedded.com; jun.li@freescale.com;
>> grygorii.strashko@ti.com; yoshihiro.shimoda.uh@renesas.com;
>> robh@kernel.org; nsekhar@ti.com; b-liu@ti.com; linux-usb@vger.kernel.org;
>> linux-omap@vger.kernel.org; linux-kernel@vger.kernel.org;
>> devicetree@vger.kernel.org
>> Subject: Re: [PATCH v8 08/14] usb: otg: add OTG/dual-role core
>>
>> On Tue, May 24, 2016 at 12:45:46PM +0300, Roger Quadros wrote:
>>> Hi Peter,
>>>
>>> I have one question here. Please see below.
>>>
>>> On 13/05/16 13:03, Roger Quadros wrote:
>>>> It provides APIs for the following tasks
>>>>
>>>> - Registering an OTG/dual-role capable controller
>>>> - Registering Host and Gadget controllers to OTG core
>>>> - Providing inputs to and kicking the OTG state machine
>>>>
>>>> Provide a dual-role device (DRD) state machine.
>>>> DRD mode is a reduced functionality OTG mode. In this mode we don't
>>>> support SRP, HNP and dynamic role-swap.
>>>>
>>>> In DRD operation, the controller mode (Host or Peripheral) is
>>>> decided based on the ID pin status. Once a cable plug (Type-A or
>>>> Type-B) is attached the controller selects the state and doesn't
>>>> change till the cable in unplugged and a different cable type is
>>>> inserted.
>>>>
>>>> As we don't need most of the complex OTG states and OTG timers we
>>>> implement a lean DRD state machine in usb-otg.c.
>>>> The DRD state machine is only interested in 2 hardware inputs 'id'
>>>> and 'b_sess_vld'.
>>>>
>>>> Signed-off-by: Roger Quadros <rogerq@ti.com>
>>>> ---
>>>>  drivers/usb/common/Makefile  |    2 +-
>>>>  drivers/usb/common/usb-otg.c | 1042
>> ++++++++++++++++++++++++++++++++++++++++++
>>>>  drivers/usb/core/Kconfig     |    4 +-
>>>>  include/linux/usb/gadget.h   |    2 +
>>>>  include/linux/usb/hcd.h      |    1 +
>>>>  include/linux/usb/otg-fsm.h  |    7 +
>>>>  include/linux/usb/otg.h      |  154 ++++++-
>>>>  7 files changed, 1206 insertions(+), 6 deletions(-)  create mode
>>>> 100644 drivers/usb/common/usb-otg.c
>>>>
>>>
>>> <snip>
>>>
>>>> +
>>>> +/**
>>>> + * usb_otg_register() - Register the OTG/dual-role device to OTG
>>>> +core
>>>> + * @dev: OTG/dual-role controller device.
>>>> + * @config: OTG configuration.
>>>> + *
>>>> + * Registers the OTG/dual-role controller device with the USB OTG
>> core.
>>>> + *
>>>> + * Return: struct usb_otg * if success, ERR_PTR() if error.
>>>> + */
>>>> +struct usb_otg *usb_otg_register(struct device *dev,
>>>> +				 struct usb_otg_config *config) {
>>>> +	struct usb_otg *otg;
>>>> +	struct otg_wait_data *wait;
>>>> +	int ret = 0;
>>>> +
>>>> +	if (!dev || !config || !config->fsm_ops)
>>>> +		return ERR_PTR(-EINVAL);
>>>> +
>>>> +	/* already in list? */
>>>> +	mutex_lock(&otg_list_mutex);
>>>> +	if (usb_otg_get_data(dev)) {
>>>> +		dev_err(dev, "otg: %s: device already in otg list\n",
>>>> +			__func__);
>>>> +		ret = -EINVAL;
>>>> +		goto unlock;
>>>> +	}
>>>> +
>>>> +	/* allocate and add to list */
>>>> +	otg = kzalloc(sizeof(*otg), GFP_KERNEL);
>>>> +	if (!otg) {
>>>> +		ret = -ENOMEM;
>>>> +		goto unlock;
>>>> +	}
>>>> +
>>>> +	otg->dev = dev;
>>>> +	otg->caps = config->otg_caps;
>>>
>>> Here, we should be checking if user needs to disable any OTG features.
>>> So,
>>>
>>> 	if (dev->of_node)
>>> 		of_usb_update_otg_caps(dev->of_node, &otg->caps);
>>>
>>> Do you agree?
>>> This means we need to change otg->caps from 'struct usb_otg_caps *caps;'
>>> to 'struct usb_otg_caps caps;' so that we can modify the local copy
>>> instead of the one passed by the OTG controller.
>>
>> Why can't modify the one from OTG controller directly?
> 
> Yes, if user wants to disable any OTG features, this should have been
> done in 'config->otg_caps', if not, 'config->otg_caps' from controller
> driver is invalid and making no sense.

I've tried to why to Peter's mail.

> 
>>
>>>
>>> We can also move of_usb_update_otg_caps() to otg.h.
>>>
>>> We will also need to modify the udc-core code so that it sets
>>> gadget->otg_caps to the modified otg_caps from the OTG core. This will
>>> ensure that the right OTG descriptors are sent.
>>>
>>> So we will have to introduce an API.
>>>
>>> struct usb_otg_caps *usb_otg_get_otg_caps(struct device *otg_dev)
>>>
>>> And in udc-core.c,
>>>
>>> static int udc_bind_to_driver(struct usb_udc *udc, struct
>>> usb_gadget_driver *driver) { ..
>>>         ret = driver->bind(udc->gadget, driver);
>>>         if (ret)
>>>                 goto err1;
>>>
>>>         /* If OTG, the otg core starts the UDC when needed */
>>>         if (udc->gadget->otg_dev) {
>>> +		udc->gadget->is_otg = true;
>>
>> gadget->is_otg is only set to true if fully OTG is supported and it
>> needs to send OTG descriptors at this case. DRD devices should not send
>> OTG descriptors.
>>
>>> +		udc->gadget->otg_caps = usb_otg_get_otg_caps(udc->gadget-
>>> otg_dev);
>>
>> Getting otg capabilities should be prior to driver->bind since
>> usb_otg_descriptor_init is called at that. Besides, Gadget driver may be
>> probed before otg driver is registered
>>
>> I am wonder if we can implement defer probe for gadget/udc/host driver if
>> otg driver is not probed, in that case, some designs can be simpler like
>> wait list in otg driver.
> 
> I even don't see much benefit of this kind of random order of OTG/HCD/GADGET
> registration, anyway OTG register can be done firstly.

You cannot control the order in systems where all 3 are implemented by separate
hardware modules. We have to consider that they can be registered
in any order and make sure it works.

returning -EPROBE_DEFER in usb_otg_add_gadget_udc()/usb_otg_add_hcd() if OTG
controller driver is not yet probed makes perfect sense and is the way to solve
this dependency issue.

> HCD and GADGET are both separated drivers, but OTG is newly added
> and what we need is just a registration in controller driver.

How do you solve the problem when host registers before OTG? I tried to solve it
using the wait_list in usb-otg.c. The other alternative is -EPROBE_DEFER during
usb_otg_add_hcd/udc().

--
cheers,
-roger

^ permalink raw reply	[flat|nested] 62+ messages in thread

* RE: [PATCH v8 08/14] usb: otg: add OTG/dual-role core
  2016-05-25 12:21       ` Roger Quadros
@ 2016-05-25 14:44         ` Jun Li
  0 siblings, 0 replies; 62+ messages in thread
From: Jun Li @ 2016-05-25 14:44 UTC (permalink / raw)
  To: Roger Quadros, Peter Chen
  Cc: peter.chen, balbi, tony, gregkh, dan.j.williams, mathias.nyman,
	Joao.Pinto, sergei.shtylyov, jun.li, grygorii.strashko,
	yoshihiro.shimoda.uh, robh, nsekhar, b-liu, linux-usb,
	linux-omap, linux-kernel, devicetree

Hi Roger

> >>
> >> Here, we should be checking if user needs to disable any OTG
> >> features. So,
> >>
> >> 	if (dev->of_node)
> >> 		of_usb_update_otg_caps(dev->of_node, &otg->caps);
> >>
> >> Do you agree?
> >> This means we need to change otg->caps from 'struct usb_otg_caps
> *caps;'
> >> to 'struct usb_otg_caps caps;' so that we can modify the local copy
> >> instead of the one passed by the OTG controller.
> >
> > Why can't modify the one from OTG controller directly?
> >
> 
> There are 2 things.
> 1) OTG features supported by hardware. This is the controller's config-
> >otg_caps
> 2) OTG features needed by system designer. This can be a subset of (1).

Let's make things simple, we only need this subnet, which can be set
by controller driver in config->otg_caps before pass (its address)
to OTG core.

So controller driver should get the capability of HW(+SW) and user config
by whatever approach, then set its config->otg_caps.

Li Jun

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v8 00/14] USB OTG/dual-role framework
  2016-05-13 10:03 [PATCH v8 00/14] USB OTG/dual-role framework Roger Quadros
                   ` (13 preceding siblings ...)
  2016-05-13 10:03 ` [PATCH v8 14/14] usb: host: xhci-plat: Add otg device to platform data Roger Quadros
@ 2016-05-30  9:29 ` Peter Chen
  2016-05-30 14:04   ` Roger Quadros
  14 siblings, 1 reply; 62+ messages in thread
From: Peter Chen @ 2016-05-30  9:29 UTC (permalink / raw)
  To: Roger Quadros
  Cc: peter.chen, balbi, tony, gregkh, dan.j.williams, mathias.nyman,
	Joao.Pinto, sergei.shtylyov, jun.li, grygorii.strashko,
	yoshihiro.shimoda.uh, robh, nsekhar, b-liu, linux-usb,
	linux-omap, linux-kernel, devicetree

On Fri, May 13, 2016 at 01:03:14PM +0300, Roger Quadros wrote:
> Hi,
> 
> This series centralizes OTG/Dual-role functionality in the kernel.
> As of now I've got Dual-role functionality working pretty reliably on
> dra7-evm and am437x-gp-evm.
> NOTE: my am437x-gp-evm broke so I couldn't test v8 on it.
> But the changes since v7 are trivial and shouldn't impact am437x-gp-evm.
> 
> DWC3 controller and platform related patches will be sent separately.
> 
> Series is based on v4.6-rc1 and depends on first 2 patches of [1]
> [1] - OTG fsm cleanup - https://lkml.org/lkml/2016/3/30/186
> 
> Why?:
> ----
> 
> Currently there is no central location where OTG/dual-role functionality is
> implemented in the Linux USB stack and every USB controller driver is
> doing their own thing for OTG/dual-role. We can benefit from code-reuse
> and simplicity by adding the OTG/dual-role core driver.
> 
> Newer OTG cores support standard host interface (e.g. xHCI) so
> host and gadget functionality are no longer closely knit like older
> cores. There needs to be a way to co-ordinate the operation of the
> host and gadget controllers in dual-role mode. i.e. to stop and start them
> from a central location. This central location should be the
> USB OTG/dual-role core.
> 
> Host and gadget controllers might be sharing resources and can't
> be always running. One has to be stopped for the other to run.
> This couldn't be done till now but can be done from the OTG core.
> 
> What?:
> -----
> 
> The OTG/dual-role core consists of a set of APIs that allow
> registration of OTG controller device and OTG capable host and gadget
> controllers.
> 
> - The OTG controller driver can provide the OTG capabilities and the
> Finite State Machine work function via 'struct usb_otg_config'
> at the time of registration i.e. usb_otg_register();
> 
> 	struct usb_otg *usb_otg_register(struct device *dev,
>         	                         struct usb_otg_config *config);
> 	int usb_otg_unregister(struct device *dev);
> 	/**
> 	 * struct usb_otg_config - otg controller configuration
> 	 * @caps: otg capabilities of the controller
> 	 * @ops: otg fsm operations
> 	 * @otg_work: optional custom otg state machine work function
> 	 */
> 	struct usb_otg_config {
> 	        struct usb_otg_caps *otg_caps;
> 	        struct otg_fsm_ops *fsm_ops;
> 	        void (*otg_work)(struct work_struct *work);
> 	};
> 
> The dual-role state machine is built-into the OTG core so nothing
> special needs to be provided if only dual-role functionality is desired.
> The low level OTG controller driver ops are povided via
> 'struct otg_fsm_ops *fsm_ops' in the 'struct usb_otg_config'.
> 
> After registration, the OTG core waits for host, gadget controller
> and the gadget function driver to be registered. Once all resources are
> available it instantiates the Finite State Machine (FSM).
> The host/gadget controllers are started/stopped according to the FSM.
> 
> - Host and gadget controllers that are a part of OTG/dual-role port must
> use the OTG core provided APIs to add/remove the host/gadget.
> i.e. hosts must use usb_otg_add_hcd() usb_otg_remove_hcd(),,
> gadgets must use usb_otg_add_gadget_udc() usb_del_gadget_udc().
> This ensures that the host and gadget controllers are not started till
> the state machine is ready and the right bus conditions are met.
> It also allows the host and gadget controllers to provide the OTG
> controller device to link them together. For Device tree boots
> the related OTG controller is automatically picked up via the
> 'otg-controller' property in the Host/Gadget controller nodes.
> 
> 	int usb_otg_add_hcd(struct usb_hcd *hcd,
> 			    unsigned int irqnum, unsigned long irqflags,
> 			    struct device *otg_dev);
> 	void usb_otg_remove_hcd(struct usb_hcd *hcd);
> 
> 	int usb_otg_add_gadget_udc(struct device *parent,
> 				   struct usb_gadget *gadget,
> 				   struct device *otg_dev);
> 	usb_del_gadget_udc() must be used for removal.
> 
> 
> - During the lifetime of the FSM, the OTG controller driver can provide
> inputs event changes using usb_otg_sync_inputs(). The OTG core will
> then schedule the FSM work function (or internal dual-role state machine)
> to update the FSM state. The FSM then calls the OTG controller
> operations (fsm_ops) as necessary.
> 	void usb_otg_sync_inputs(struct usb_otg *otg);
> 
> - The following 2 functions are provided as helpers for use by the
> OTG controller driver to start/stop the host/gadget controllers.
> 	int usb_otg_start_host(struct usb_otg *otg, int on);
> 	int usb_otg_start_gadget(struct usb_otg *otg, int on);
> 
> - The following function is provided for use by the USB host stack
> to sync OTG related events to the OTG state machine.
> e.g. change in host_bus->b_hnp_enable, gadget->b_hnp_enable
> 	int usb_otg_kick_fsm(struct device *otg_device);
> 
> Changelog:
> ---------
> v8:
> - split out start/stop gadget and connect/disconnect operations.
> - make CONFIG_OTG dpend on CONFIG_USB_GADGET as well apart from CONFIG_USB
> - use create_freezable_workqueue() for OTG work as per Peter's suggestion.
> - remove usb-otg.h as we're not initializing any OTG timers.
> - don't include unnecessary headers in usb-otg.c (i.e. hrtimer.h & ktime.h)
> 

Since you have agreed to move CONFIG_USB_OTG out of HCD, I suggest you
can have a folder to put current OTG and OTG_FSM stuffs under the root
of usb folder, it can benefit the user who wants to add their dual-role
switch driver or OTG driver. What do you think?

Peter
> v7:
> - added dual-role support for host controllers requiring a companion
> controller. e.g. EHCI + OHCI.
> - added of_usb_get_otg() to get the OTG controller device
> from the USB controller's device node.
> - addressed review comments.
> 
> v6:
> - added otg specific APIs for host/gadget registration. behaviour of
> original host/gadget API remains unchanged. Platform devices can now
> pass the otg device explicitly while registering host/gadget.
> - moved hcd specific operations from struct otg_fsm to struct hcd_ops.
> - made struct usb_otg mandatory for all otg related APIs.
> - allow otg controller to provide it's own otg_work function so that
> it can implement it's own state machine.
> - removed otg fsm and timers from usb-otg.c. Only dual-role state machine
> is implemented.
> - vbus is controlled in the dual-role state machine.
> - PM runtime is used around drd_statemachine().
> - added otg_dev to xhci platform data to allow platform code to specify
> the otg controller tied to the xhci host controller.
> 
> v5: Internal version. Not sent to mailing list
> 
> v4:
> - Added DT support for tying otg-controller to host and gadget
>  controllers. For DT we no longer have the constraint that
>  OTG controller needs to be parent of host and gadget. They can be
>  tied together using the "otg-controller" property.
> - Relax the requirement for DT case that otg controller must register
>  before host/gadget. We maintain a wait list of host/gadget devices
>  waiting on the otg controller.
> - Use a single struct usb_otg for otg data.
> - Don't override host/gadget start/stop APIs. Let the controller
>  drivers do what they want as they know best. Helper API is provided
>  for controller start/stop that controller driver can use.
> - Introduce struct usb_otg_config to pass the otg capabilities,
>  otg ops and otg timer timeouts during otg controller registration.
> - rebased on Greg's usb.git/usb-next
> 
> v3:
> - all otg related definations now in otg.h
> - single kernel config USB_OTG to enable OTG core and FSM.
> - resolved symbol dependency issues.
> - use dev_vdbg instead of VDBG() in usb-otg-fsm.c
> - rebased on v4.2-rc1
> 
> v2:
> - Use add/remove_hcd() instead of start/stop_hcd() to enable/disable
>  the host controller
> - added dual-role-device (DRD) state machine which is a much simpler
>  mode of operation when compared to OTG. Here we don't support fancy
>  OTG features like HNP, SRP, on the fly role-swap. The mode of operation
>  is determined based on ID pin (cable type) and the role doesn't change
>  till the cable type changes.
> 
> --
> cheers,
> -roger
> 
> Roger Quadros (13):
>   usb: hcd: Initialize hcd->flags to 0
>   usb: otg-fsm: Prevent build warning "VDBG" redefined
>   usb: hcd.h: Add OTG to HCD interface
>   usb: otg-fsm: use usb_otg wherever possible
>   usb: otg-fsm: move host controller operations into usb_otg->hcd_ops
>   usb: gadget.h: Add OTG to gadget interface
>   usb: otg: get rid of CONFIG_USB_OTG_FSM in favour of CONFIG_USB_OTG
>   usb: otg: add OTG/dual-role core
>   usb: of: add an API to get OTG device from USB controller node
>   usb: otg: use dev_dbg() instead of VDBG()
>   usb: hcd: Adapt to OTG core
>   usb: gadget: udc: adapt to OTG core
>   usb: host: xhci-plat: Add otg device to platform data
> 
> Yoshihiro Shimoda (1):
>   usb: otg: add hcd companion support
> 
>  Documentation/devicetree/bindings/usb/generic.txt |    6 +
>  Documentation/usb/chipidea.txt                    |    2 +-
>  drivers/usb/chipidea/Makefile                     |    2 +-
>  drivers/usb/chipidea/ci.h                         |    3 +-
>  drivers/usb/chipidea/core.c                       |   14 +-
>  drivers/usb/chipidea/debug.c                      |    2 +-
>  drivers/usb/chipidea/otg_fsm.c                    |  176 ++--
>  drivers/usb/chipidea/otg_fsm.h                    |    2 +-
>  drivers/usb/chipidea/udc.c                        |   17 +-
>  drivers/usb/common/Makefile                       |    3 +-
>  drivers/usb/common/common.c                       |   27 +
>  drivers/usb/common/usb-otg-fsm.c                  |  203 ++--
>  drivers/usb/common/usb-otg.c                      | 1056 +++++++++++++++++++++
>  drivers/usb/core/Kconfig                          |   12 +-
>  drivers/usb/core/hcd.c                            |   56 ++
>  drivers/usb/gadget/udc/udc-core.c                 |  194 +++-
>  drivers/usb/host/xhci-plat.c                      |   35 +-
>  drivers/usb/phy/Kconfig                           |    2 +-
>  drivers/usb/phy/phy-fsl-usb.c                     |  155 +--
>  drivers/usb/phy/phy-fsl-usb.h                     |    3 +-
>  include/linux/usb/gadget.h                        |   22 +
>  include/linux/usb/hcd.h                           |   29 +
>  include/linux/usb/of.h                            |    9 +
>  include/linux/usb/otg-fsm.h                       |  154 +--
>  include/linux/usb/otg.h                           |  264 +++++-
>  include/linux/usb/xhci_pdriver.h                  |    3 +
>  26 files changed, 2013 insertions(+), 438 deletions(-)
>  create mode 100644 drivers/usb/common/usb-otg.c
> 
> -- 
> 2.7.4
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-usb" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

-- 

Best Regards,
Peter Chen

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v8 00/14] USB OTG/dual-role framework
  2016-05-30  9:29 ` [PATCH v8 00/14] USB OTG/dual-role framework Peter Chen
@ 2016-05-30 14:04   ` Roger Quadros
  0 siblings, 0 replies; 62+ messages in thread
From: Roger Quadros @ 2016-05-30 14:04 UTC (permalink / raw)
  To: Peter Chen
  Cc: peter.chen, balbi, tony, gregkh, dan.j.williams, mathias.nyman,
	Joao.Pinto, sergei.shtylyov, jun.li, grygorii.strashko,
	yoshihiro.shimoda.uh, robh, nsekhar, b-liu, linux-usb,
	linux-omap, linux-kernel, devicetree

On 30/05/16 12:29, Peter Chen wrote:
> On Fri, May 13, 2016 at 01:03:14PM +0300, Roger Quadros wrote:
>> Hi,
>>
>> This series centralizes OTG/Dual-role functionality in the kernel.
>> As of now I've got Dual-role functionality working pretty reliably on
>> dra7-evm and am437x-gp-evm.
>> NOTE: my am437x-gp-evm broke so I couldn't test v8 on it.
>> But the changes since v7 are trivial and shouldn't impact am437x-gp-evm.
>>
>> DWC3 controller and platform related patches will be sent separately.
>>
>> Series is based on v4.6-rc1 and depends on first 2 patches of [1]
>> [1] - OTG fsm cleanup - https://lkml.org/lkml/2016/3/30/186
>>
>> Why?:
>> ----
>>
>> Currently there is no central location where OTG/dual-role functionality is
>> implemented in the Linux USB stack and every USB controller driver is
>> doing their own thing for OTG/dual-role. We can benefit from code-reuse
>> and simplicity by adding the OTG/dual-role core driver.
>>
>> Newer OTG cores support standard host interface (e.g. xHCI) so
>> host and gadget functionality are no longer closely knit like older
>> cores. There needs to be a way to co-ordinate the operation of the
>> host and gadget controllers in dual-role mode. i.e. to stop and start them
>> from a central location. This central location should be the
>> USB OTG/dual-role core.
>>
>> Host and gadget controllers might be sharing resources and can't
>> be always running. One has to be stopped for the other to run.
>> This couldn't be done till now but can be done from the OTG core.
>>
>> What?:
>> -----
>>
>> The OTG/dual-role core consists of a set of APIs that allow
>> registration of OTG controller device and OTG capable host and gadget
>> controllers.
>>
>> - The OTG controller driver can provide the OTG capabilities and the
>> Finite State Machine work function via 'struct usb_otg_config'
>> at the time of registration i.e. usb_otg_register();
>>
>> 	struct usb_otg *usb_otg_register(struct device *dev,
>>         	                         struct usb_otg_config *config);
>> 	int usb_otg_unregister(struct device *dev);
>> 	/**
>> 	 * struct usb_otg_config - otg controller configuration
>> 	 * @caps: otg capabilities of the controller
>> 	 * @ops: otg fsm operations
>> 	 * @otg_work: optional custom otg state machine work function
>> 	 */
>> 	struct usb_otg_config {
>> 	        struct usb_otg_caps *otg_caps;
>> 	        struct otg_fsm_ops *fsm_ops;
>> 	        void (*otg_work)(struct work_struct *work);
>> 	};
>>
>> The dual-role state machine is built-into the OTG core so nothing
>> special needs to be provided if only dual-role functionality is desired.
>> The low level OTG controller driver ops are povided via
>> 'struct otg_fsm_ops *fsm_ops' in the 'struct usb_otg_config'.
>>
>> After registration, the OTG core waits for host, gadget controller
>> and the gadget function driver to be registered. Once all resources are
>> available it instantiates the Finite State Machine (FSM).
>> The host/gadget controllers are started/stopped according to the FSM.
>>
>> - Host and gadget controllers that are a part of OTG/dual-role port must
>> use the OTG core provided APIs to add/remove the host/gadget.
>> i.e. hosts must use usb_otg_add_hcd() usb_otg_remove_hcd(),,
>> gadgets must use usb_otg_add_gadget_udc() usb_del_gadget_udc().
>> This ensures that the host and gadget controllers are not started till
>> the state machine is ready and the right bus conditions are met.
>> It also allows the host and gadget controllers to provide the OTG
>> controller device to link them together. For Device tree boots
>> the related OTG controller is automatically picked up via the
>> 'otg-controller' property in the Host/Gadget controller nodes.
>>
>> 	int usb_otg_add_hcd(struct usb_hcd *hcd,
>> 			    unsigned int irqnum, unsigned long irqflags,
>> 			    struct device *otg_dev);
>> 	void usb_otg_remove_hcd(struct usb_hcd *hcd);
>>
>> 	int usb_otg_add_gadget_udc(struct device *parent,
>> 				   struct usb_gadget *gadget,
>> 				   struct device *otg_dev);
>> 	usb_del_gadget_udc() must be used for removal.
>>
>>
>> - During the lifetime of the FSM, the OTG controller driver can provide
>> inputs event changes using usb_otg_sync_inputs(). The OTG core will
>> then schedule the FSM work function (or internal dual-role state machine)
>> to update the FSM state. The FSM then calls the OTG controller
>> operations (fsm_ops) as necessary.
>> 	void usb_otg_sync_inputs(struct usb_otg *otg);
>>
>> - The following 2 functions are provided as helpers for use by the
>> OTG controller driver to start/stop the host/gadget controllers.
>> 	int usb_otg_start_host(struct usb_otg *otg, int on);
>> 	int usb_otg_start_gadget(struct usb_otg *otg, int on);
>>
>> - The following function is provided for use by the USB host stack
>> to sync OTG related events to the OTG state machine.
>> e.g. change in host_bus->b_hnp_enable, gadget->b_hnp_enable
>> 	int usb_otg_kick_fsm(struct device *otg_device);
>>
>> Changelog:
>> ---------
>> v8:
>> - split out start/stop gadget and connect/disconnect operations.
>> - make CONFIG_OTG dpend on CONFIG_USB_GADGET as well apart from CONFIG_USB
>> - use create_freezable_workqueue() for OTG work as per Peter's suggestion.
>> - remove usb-otg.h as we're not initializing any OTG timers.
>> - don't include unnecessary headers in usb-otg.c (i.e. hrtimer.h & ktime.h)
>>
> 
> Since you have agreed to move CONFIG_USB_OTG out of HCD, I suggest you
> can have a folder to put current OTG and OTG_FSM stuffs under the root
> of usb folder, it can benefit the user who wants to add their dual-role
> switch driver or OTG driver. What do you think?

Yes, I will give it a try and post if any problems.

--
cheers,
-roger

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v8 13/14] usb: gadget: udc: adapt to OTG core
  2016-05-13 10:03 ` [PATCH v8 13/14] usb: gadget: udc: adapt " Roger Quadros
  2016-05-16  7:02   ` Peter Chen
@ 2016-06-01  7:38   ` Peter Chen
  2016-06-02 11:07     ` Roger Quadros
  1 sibling, 1 reply; 62+ messages in thread
From: Peter Chen @ 2016-06-01  7:38 UTC (permalink / raw)
  To: Roger Quadros
  Cc: peter.chen, balbi, tony, gregkh, dan.j.williams, mathias.nyman,
	Joao.Pinto, sergei.shtylyov, jun.li, grygorii.strashko,
	yoshihiro.shimoda.uh, robh, nsekhar, b-liu, linux-usb,
	linux-omap, linux-kernel, devicetree

On Fri, May 13, 2016 at 01:03:27PM +0300, Roger Quadros wrote:
> @@ -530,6 +683,8 @@ void usb_del_gadget_udc(struct usb_gadget *gadget)
>  	}
>  	mutex_unlock(&udc_lock);
>  
> +	mutex_unlock(&udc_lock);
> +

Here, you have one more mutex_unlock.

Peter
>  	kobject_uevent(&udc->dev.kobj, KOBJ_REMOVE);
>  	flush_work(&gadget->work);
>  	device_unregister(&udc->dev);
> @@ -539,6 +694,13 @@ EXPORT_SYMBOL_GPL(usb_del_gadget_udc);
>  
>  /* ------------------------------------------------------------------------- */
>  
> +struct otg_gadget_ops otg_gadget_intf = {
> +	.start = usb_gadget_start,
> +	.stop = usb_gadget_stop,
> +	.connect_control = usb_gadget_connect_control,
> +};
> +
> +/* udc_lock must be held */
>  static int udc_bind_to_driver(struct usb_udc *udc, struct usb_gadget_driver *driver)
>  {
>  	int ret;
> @@ -553,12 +715,20 @@ static int udc_bind_to_driver(struct usb_udc *udc, struct usb_gadget_driver *dri
>  	ret = driver->bind(udc->gadget, driver);
>  	if (ret)
>  		goto err1;
> -	ret = usb_gadget_udc_start(udc);
> -	if (ret) {
> -		driver->unbind(udc->gadget);
> -		goto err1;
> +
> +	/* If OTG, the otg core starts the UDC when needed */
> +	if (udc->gadget->otg_dev) {
> +		mutex_unlock(&udc_lock);
> +		usb_otg_register_gadget(udc->gadget, &otg_gadget_intf);
> +		mutex_lock(&udc_lock);
> +	} else {
> +		ret = usb_gadget_udc_start(udc);
> +		if (ret) {
> +			driver->unbind(udc->gadget);
> +			goto err1;
> +		}
> +		usb_udc_connect_control(udc);
>  	}
> -	usb_udc_connect_control(udc);
>  
>  	kobject_uevent(&udc->dev.kobj, KOBJ_CHANGE);
>  	return 0;
> @@ -660,9 +830,15 @@ static ssize_t usb_udc_softconn_store(struct device *dev,
>  		return -EOPNOTSUPP;
>  	}
>  
> +	/* In OTG mode we don't support softconnect, but b_bus_req */
> +	if (udc->gadget->otg_dev) {
> +		dev_err(dev, "soft-connect not supported in OTG mode\n");
> +		return -EOPNOTSUPP;
> +	}
> +
>  	if (sysfs_streq(buf, "connect")) {
>  		usb_gadget_udc_start(udc);
> -		usb_gadget_connect(udc->gadget);
> +		usb_udc_connect_control(udc);
>  	} else if (sysfs_streq(buf, "disconnect")) {
>  		usb_gadget_disconnect(udc->gadget);
>  		udc->driver->disconnect(udc->gadget);
> diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h
> index 3ecfddd..79d654f 100644
> --- a/include/linux/usb/gadget.h
> +++ b/include/linux/usb/gadget.h
> @@ -1162,6 +1162,10 @@ extern int usb_add_gadget_udc(struct device *parent, struct usb_gadget *gadget);
>  extern void usb_del_gadget_udc(struct usb_gadget *gadget);
>  extern char *usb_get_gadget_udc_name(void);
>  
> +extern int usb_otg_add_gadget_udc(struct device *parent,
> +				  struct usb_gadget *gadget,
> +				  struct device *otg_dev);
> +
>  /*-------------------------------------------------------------------------*/
>  
>  /* utility to simplify dealing with string descriptors */
> -- 
> 2.7.4
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-usb" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

-- 

Best Regards,
Peter Chen

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v8 13/14] usb: gadget: udc: adapt to OTG core
  2016-06-01  7:38   ` Peter Chen
@ 2016-06-02 11:07     ` Roger Quadros
  0 siblings, 0 replies; 62+ messages in thread
From: Roger Quadros @ 2016-06-02 11:07 UTC (permalink / raw)
  To: Peter Chen
  Cc: peter.chen, balbi, tony, gregkh, dan.j.williams, mathias.nyman,
	Joao.Pinto, sergei.shtylyov, jun.li, grygorii.strashko,
	yoshihiro.shimoda.uh, robh, nsekhar, b-liu, linux-usb,
	linux-omap, linux-kernel, devicetree

On 01/06/16 10:38, Peter Chen wrote:
> On Fri, May 13, 2016 at 01:03:27PM +0300, Roger Quadros wrote:
>> @@ -530,6 +683,8 @@ void usb_del_gadget_udc(struct usb_gadget *gadget)
>>  	}
>>  	mutex_unlock(&udc_lock);
>>  
>> +	mutex_unlock(&udc_lock);
>> +
> 
> Here, you have one more mutex_unlock.

Will fix it. Thanks.

>>  	kobject_uevent(&udc->dev.kobj, KOBJ_REMOVE);
>>  	flush_work(&gadget->work);
>>  	device_unregister(&udc->dev);
>> @@ -539,6 +694,13 @@ EXPORT_SYMBOL_GPL(usb_del_gadget_udc);
>>  
>>  /* ------------------------------------------------------------------------- */
>>  
>> +struct otg_gadget_ops otg_gadget_intf = {
>> +	.start = usb_gadget_start,
>> +	.stop = usb_gadget_stop,
>> +	.connect_control = usb_gadget_connect_control,
>> +};
>> +
>> +/* udc_lock must be held */
>>  static int udc_bind_to_driver(struct usb_udc *udc, struct usb_gadget_driver *driver)
>>  {
>>  	int ret;
>> @@ -553,12 +715,20 @@ static int udc_bind_to_driver(struct usb_udc *udc, struct usb_gadget_driver *dri
>>  	ret = driver->bind(udc->gadget, driver);
>>  	if (ret)
>>  		goto err1;
>> -	ret = usb_gadget_udc_start(udc);
>> -	if (ret) {
>> -		driver->unbind(udc->gadget);
>> -		goto err1;
>> +
>> +	/* If OTG, the otg core starts the UDC when needed */
>> +	if (udc->gadget->otg_dev) {
>> +		mutex_unlock(&udc_lock);
>> +		usb_otg_register_gadget(udc->gadget, &otg_gadget_intf);
>> +		mutex_lock(&udc_lock);
>> +	} else {
>> +		ret = usb_gadget_udc_start(udc);
>> +		if (ret) {
>> +			driver->unbind(udc->gadget);
>> +			goto err1;
>> +		}
>> +		usb_udc_connect_control(udc);
>>  	}
>> -	usb_udc_connect_control(udc);
>>  
>>  	kobject_uevent(&udc->dev.kobj, KOBJ_CHANGE);
>>  	return 0;
>> @@ -660,9 +830,15 @@ static ssize_t usb_udc_softconn_store(struct device *dev,
>>  		return -EOPNOTSUPP;
>>  	}
>>  
>> +	/* In OTG mode we don't support softconnect, but b_bus_req */
>> +	if (udc->gadget->otg_dev) {
>> +		dev_err(dev, "soft-connect not supported in OTG mode\n");
>> +		return -EOPNOTSUPP;
>> +	}
>> +
>>  	if (sysfs_streq(buf, "connect")) {
>>  		usb_gadget_udc_start(udc);
>> -		usb_gadget_connect(udc->gadget);
>> +		usb_udc_connect_control(udc);
>>  	} else if (sysfs_streq(buf, "disconnect")) {
>>  		usb_gadget_disconnect(udc->gadget);
>>  		udc->driver->disconnect(udc->gadget);
>> diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h
>> index 3ecfddd..79d654f 100644
>> --- a/include/linux/usb/gadget.h
>> +++ b/include/linux/usb/gadget.h
>> @@ -1162,6 +1162,10 @@ extern int usb_add_gadget_udc(struct device *parent, struct usb_gadget *gadget);
>>  extern void usb_del_gadget_udc(struct usb_gadget *gadget);
>>  extern char *usb_get_gadget_udc_name(void);
>>  
>> +extern int usb_otg_add_gadget_udc(struct device *parent,
>> +				  struct usb_gadget *gadget,
>> +				  struct device *otg_dev);
>> +
>>  /*-------------------------------------------------------------------------*/
>>  
>>  /* utility to simplify dealing with string descriptors */
>> -- 
>> 2.7.4
>>

--
cheers,
-roger

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v8 13/14] usb: gadget: udc: adapt to OTG core
  2016-05-24  2:53                                     ` Peter Chen
@ 2016-06-08  7:32                                       ` Roger Quadros
  2016-06-08  9:05                                         ` Peter Chen
  0 siblings, 1 reply; 62+ messages in thread
From: Roger Quadros @ 2016-06-08  7:32 UTC (permalink / raw)
  To: Peter Chen
  Cc: Jun Li, peter.chen, balbi, tony, gregkh, dan.j.williams,
	mathias.nyman, Joao.Pinto, sergei.shtylyov, jun.li,
	grygorii.strashko, yoshihiro.shimoda.uh, robh, nsekhar, b-liu,
	linux-usb, linux-omap, linux-kernel, devicetree

Hi,

On 24/05/16 05:53, Peter Chen wrote:
> On Mon, May 23, 2016 at 01:36:51PM +0300, Roger Quadros wrote:
>> On 23/05/16 13:34, Jun Li wrote:
>>> Hi
>>>
>>>> -----Original Message-----
>>>> From: Roger Quadros [mailto:rogerq@ti.com]
>>>> Sent: Monday, May 23, 2016 6:12 PM
>>>> To: Peter Chen <hzpeterchen@gmail.com>
>>>> Cc: Jun Li <jun.li@nxp.com>; peter.chen@freescale.com; balbi@kernel.org;
>>>> tony@atomide.com; gregkh@linuxfoundation.org; dan.j.williams@intel.com;
>>>> mathias.nyman@linux.intel.com; Joao.Pinto@synopsys.com;
>>>> sergei.shtylyov@cogentembedded.com; jun.li@freescale.com;
>>>> grygorii.strashko@ti.com; yoshihiro.shimoda.uh@renesas.com;
>>>> robh@kernel.org; nsekhar@ti.com; b-liu@ti.com; linux-usb@vger.kernel.org;
>>>> linux-omap@vger.kernel.org; linux-kernel@vger.kernel.org;
>>>> devicetree@vger.kernel.org
>>>> Subject: Re: [PATCH v8 13/14] usb: gadget: udc: adapt to OTG core
>>>>
>>>> On 23/05/16 06:21, Peter Chen wrote:
>>>>> On Sat, May 21, 2016 at 10:29:40AM +0800, Peter Chen wrote:
>>>>>> On Thu, May 19, 2016 at 10:32:44AM +0300, Roger Quadros wrote:
>>>>>>> On 18/05/16 17:46, Jun Li wrote:
>>>>>>>>
>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> I didn't want to have complex Kconfig so decided to have otg as
>>>>>>>>>>> built-in only.
>>>>>>>>>>> What do you want me to change in existing code? and why?
>>>>>>>>>>
>>>>>>>>>> Remove those stuff which only for pass diff driver config Like
>>>>>>>>>> every controller driver need a duplicated
>>>>>>>>>>
>>>>>>>>>> static struct otg_hcd_ops ci_hcd_ops = {
>>>>>>>>>>     ...
>>>>>>>>>> }
>>>>>>>>>
>>>>>>>>> This is an exception only. Every controller driver doesn't need to
>>>>>>>>> implement hcd_ops. It is implemented in the hcd core.
>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> And here is another example, for gadget connect, otg driver can
>>>>>>>>>> directly call to usb_udc_vbus_handler() in drd state machine, but
>>>>>>>>>> you create another interface:
>>>>>>>>>>
>>>>>>>>>> .connect_control = usb_gadget_connect_control,
>>>>>>>>>>
>>>>>>>>>> If the symbol is defined in one driver which is 'm', another
>>>>>>>>>> driver reference it should be 'm' as well, then there is no this
>>>>>>>>>> kind of problem as my understanding.
>>>>>>>>>
>>>>>>>>> That is fine as long as all are 'm'. but how do you solve the case
>>>>>>>>> when Gadget is built in and host is 'm'? OTG has to be built-in
>>>>>>>>> and you will need an hcd to gadget interface.
>>>>>>>>
>>>>>>>> Hcd to gadget interface? Or you want to say otg to host interface?
>>>>>>>
>>>>>>> Sorry, I meant to say host to otg interface.
>>>>>>>
>>>>>>>>
>>>>>>>> I think hcd and gadget are independent each other, now
>>>>>>>>
>>>>>>>> Hcd --> otg; and gadget --> otg, (hcd and gadget use otg's symbol)
>>>>>>>
>>>>>>> It is actually a circular dependency for both.
>>>>>>>  hcd <--> otg and gadget <--> otg
>>>>>>>
>>>>>>> hcd -> otg for usb_otg_register/unregister_hcd otg -> hcd for
>>>>>>> usb_add/remove_hcd, usb_bus_start_enum, usb_control_msg,
>>>>>>> usb_hub_find_child
>>>>>>>
>>>>>>> gadget -> otg for usb_otg_register/unregister_gadget
>>>>>>> otg -> gadget for usb_gadget_start/stop, usb_udc_vbus_handler
>>>>>>>
>>>>>>> Now consider what will happen if I get rid of the otg_hcd and
>>>> otg_gadget interfaces.
>>>>>>> 'y' means built-in, 'm' means module.
>>>>>>>
>>>>>>> 1) hcd 'y', gadget 'y'
>>>>>>> otg has to be 'y' for proper build.
>>>>>>>
>>>>>>> 2) hcd 'm', gadget 'm'
>>>>>>> otg has to be 'm' for proper build.
>>>>>>>
>>>>>>> 3) hcd 'y', gadget 'm'
>>>>>>> Build will fail always.
>>>>>>> If otg is 'y', otg build will fail due to dependency on gadget.
>>>>>>> If otg is 'm', hcd build will fail due to dependency on otg.
>>>>>>>
>>>>>>> 4) hcd 'm', gadget 'y'
>>>>>>> Build will fail always.
>>>>>>> If otg is 'y', otg build will fail due to dependency on hcd.
>>>>>>> If otg is 'm', gadget build will fails due to dependency on otg.
>>>>>>>
>>>>>>> So I solve this problem by adding the otg_hcd_ops and otg_gadget_ops
>>>>>>> to remove otg->hcd and otg->gadget dependency.
>>>>>>>
>>>>>>> Now we can address 3) and 4) like so
>>>>>>>
>>>>>>> 3) hcd 'y', gadget 'm'
>>>>>>> otg has to be 'y' for proper build.
>>>>>>>
>>>>>>> 4) hcd 'm', gadget 'y'
>>>>>>> otg has to be 'y' for proper build.
>>>>>>>
>>>>>>
>>>>>> How about this:
>>>>>> Moving usb_otg_register/unregister_hcd to host driver to remove
>>>>>> dependency hcd->otg. And moving usb_otg_get_data to common.c.
>>>>>>
>>>>>> Delete the wait queue at usb-otg.c, and if calling usb_otg_get_data
>>>>>> returns NULL, the host/device driver's probe return -EPROBE_DEFER.
>>>>>> When the otg driver is probed successfully, the host/device will be
>>>>>> re-probed again, and usb_otg_register_hcd will be called again.
>>>>>>
>>>>>> And let OTG depends on HCD && GADGET, and delete otg_hcd_ops and
>>>>>> otg_gadget_ops. Below build dependency issues can be fixed.
>>>>>> What do you think?
>>>>>>
>>>>>>> 1) hcd 'y', gadget 'y'
>>>>>>> otg has to be 'y' for proper build.
>>>>>>>
>>>>>>> 2) hcd 'm', gadget 'm'
>>>>>>> otg has to be 'm' for proper build.
>>>>>>>
>>>>>>> 3) hcd 'y', gadget 'm'
>>>>>>> Build will fail always.
>>>>>>> If otg is 'y', otg build will fail due to dependency on gadget.
>>>>>>> If otg is 'm', hcd build will fail due to dependency on otg.
>>>>>>>
>>>>>>> 4) hcd 'm', gadget 'y'
>>>>>>> Build will fail always.
>>>>>>> If otg is 'y', otg build will fail due to dependency on hcd.
>>>>>>> If otg is 'm', gadget build will fails due to dependency on otg.
>>>>>> --
>>>>>>
>>>>>
>>>>> After thinking more, my suggestion can't work. How about moving
>>>>> CONFIG_USB_OTG out of CONFIG_USB, in that case, CONFIG_USB_OTG can
>>>>> only be built in.
>>>>>
>>>> I tried this but it still doesn't resolve 3 and 4. I.e.
>>>> it can't be automatically set to 'y' when either of hcd/gadget is 'y'
>>>> and the other is 'm'.
>>>
>>> USB_OTG only can be selected by *user*, can't be automatically set to
>>> 'y' like you said, no matter what's hcd/gadget config, USB_OTG can be
>>> disabled in any cases.
>>
>> Yes. I am on the same page with that.
>>>
>>> I think Peter's intention is to make USB_OTG to be 'bool', either disabled;
>>> or built-in(if enabled), something like your original idea?
>>
>> I'm fine with my original idea if you guys can confirm :).
>>
> 
> Please do it.
> 

OK. I managed to fix this and get usbotg to be as module when both USB and GADGET
are modules with the following patch.

What we do is use USB_OTG_CORE as a hidden tristate symbol that is used to build usbotg.o
only if USB_OTG is enabled.

USB_OTG is used to enable/disable OTG and it has to be bool since it is used at mutiple
places in the code.

cheers,
-roger

---

diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig
index 8689dcb..ed596ec 100644
--- a/drivers/usb/Kconfig
+++ b/drivers/usb/Kconfig
@@ -32,6 +32,23 @@ if USB_SUPPORT
 config USB_COMMON
 	tristate
 
+config USB_OTG_CORE
+	tristate
+
+config USB_OTG
+	bool "OTG/Dual-role support"
+	depends on PM && USB && USB_GADGET
+	default n
+	---help---
+	  The most notable feature of USB OTG is support for a
+	  "Dual-Role" device, which can act as either a device
+	  or a host. The initial role is decided by the type of
+	  plug inserted and can be changed later when two dual
+	  role devices talk to each other.
+
+	  Select this only if your board has Mini-AB/Micro-AB
+	  connector.
+
 config USB_ARCH_HAS_HCD
 	def_bool y
 
@@ -40,6 +57,7 @@ config USB
 	tristate "Support for Host-side USB"
 	depends on USB_ARCH_HAS_HCD
 	select USB_COMMON
+	select USB_OTG_CORE
 	select NLS  # for UTF-8 strings
 	---help---
 	  Universal Serial Bus (USB) is a specification for a serial bus
diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile
index 16a5b55..03f7204 100644
--- a/drivers/usb/Makefile
+++ b/drivers/usb/Makefile
@@ -59,6 +59,6 @@ obj-$(CONFIG_USB_RENESAS_USBHS)	+= renesas_usbhs/
 obj-$(CONFIG_USB_GADGET)	+= gadget/
 
 obj-$(CONFIG_USB_COMMON)	+= common/
-obj-$(CONFIG_USB_OTG)		+= common/
+obj-$(CONFIG_USB_OTG_CORE)	+= common/
 
 obj-$(CONFIG_USBIP_CORE)	+= usbip/
diff --git a/drivers/usb/common/Makefile b/drivers/usb/common/Makefile
index 730d928..5122b3f 100644
--- a/drivers/usb/common/Makefile
+++ b/drivers/usb/common/Makefile
@@ -7,5 +7,7 @@ usb-common-y			  += common.o
 usb-common-$(CONFIG_USB_LED_TRIG) += led.o
 
 obj-$(CONFIG_USB_ULPI_BUS)	+= ulpi.o
+ifeq ($(CONFIG_USB_OTG),y)
 usbotg-y		:= usb-otg.o usb-otg-fsm.o
-obj-$(CONFIG_USB_OTG)	+= usbotg.o
+obj-$(CONFIG_USB_OTG_CORE)	+= usbotg.o
+endif
diff --git a/drivers/usb/common/usb-otg.c b/drivers/usb/common/usb-otg.c
index f5eb7f5..98fcfa2 100644
--- a/drivers/usb/common/usb-otg.c
+++ b/drivers/usb/common/usb-otg.c
@@ -16,6 +16,7 @@
 
 #include <linux/kernel.h>
 #include <linux/list.h>
+#include <linux/module.h>
 #include <linux/of.h>
 #include <linux/of_platform.h>
 #include <linux/usb/of.h>
@@ -841,3 +842,5 @@ int usb_otg_gadget_ready(struct usb_gadget *gadget, bool ready)
 	return 0;
 }
 EXPORT_SYMBOL_GPL(usb_otg_gadget_ready);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/core/Kconfig b/drivers/usb/core/Kconfig
index de371e6..37f8c54 100644
--- a/drivers/usb/core/Kconfig
+++ b/drivers/usb/core/Kconfig
@@ -41,20 +41,6 @@ config USB_DYNAMIC_MINORS
 
 	  If you are unsure about this, say N here.
 
-config USB_OTG
-	bool "OTG/Dual-role support"
-	depends on PM && USB_GADGET
-	default n
-	help
-	  The most notable feature of USB OTG is support for a
-	  "Dual-Role" device, which can act as either a device
-	  or a host. The initial role is decided by the type of
-	  plug inserted and can be changed later when two dual
-	  role devices talk to each other.
-
-	  Select this only if your board has Mini-AB/Micro-AB
-	  connector.
-
 config USB_OTG_WHITELIST
 	bool "Rely on OTG and EH Targeted Peripherals List"
 	depends on USB
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index 2057add..9d55384 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -16,6 +16,7 @@
 menuconfig USB_GADGET
 	tristate "USB Gadget Support"
 	select USB_COMMON
+	select USB_OTG_CORE
 	select NLS
 	help
 	   USB is a master/slave protocol, organized with one master
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* Re: [PATCH v8 13/14] usb: gadget: udc: adapt to OTG core
  2016-06-08  7:32                                       ` Roger Quadros
@ 2016-06-08  9:05                                         ` Peter Chen
  0 siblings, 0 replies; 62+ messages in thread
From: Peter Chen @ 2016-06-08  9:05 UTC (permalink / raw)
  To: Roger Quadros
  Cc: Jun Li, peter.chen, balbi, tony, gregkh, dan.j.williams,
	mathias.nyman, Joao.Pinto, sergei.shtylyov, jun.li,
	grygorii.strashko, yoshihiro.shimoda.uh, robh, nsekhar, b-liu,
	linux-usb, linux-omap, linux-kernel, devicetree

On Wed, Jun 08, 2016 at 10:32:19AM +0300, Roger Quadros wrote:
> Hi,
> 
> On 24/05/16 05:53, Peter Chen wrote:
> > On Mon, May 23, 2016 at 01:36:51PM +0300, Roger Quadros wrote:
> >> On 23/05/16 13:34, Jun Li wrote:
> >>> Hi
> >>>
> >>>> -----Original Message-----
> >>>> From: Roger Quadros [mailto:rogerq@ti.com]
> >>>> Sent: Monday, May 23, 2016 6:12 PM
> >>>> To: Peter Chen <hzpeterchen@gmail.com>
> >>>> Cc: Jun Li <jun.li@nxp.com>; peter.chen@freescale.com; balbi@kernel.org;
> >>>> tony@atomide.com; gregkh@linuxfoundation.org; dan.j.williams@intel.com;
> >>>> mathias.nyman@linux.intel.com; Joao.Pinto@synopsys.com;
> >>>> sergei.shtylyov@cogentembedded.com; jun.li@freescale.com;
> >>>> grygorii.strashko@ti.com; yoshihiro.shimoda.uh@renesas.com;
> >>>> robh@kernel.org; nsekhar@ti.com; b-liu@ti.com; linux-usb@vger.kernel.org;
> >>>> linux-omap@vger.kernel.org; linux-kernel@vger.kernel.org;
> >>>> devicetree@vger.kernel.org
> >>>> Subject: Re: [PATCH v8 13/14] usb: gadget: udc: adapt to OTG core
> >>>>
> >>>> On 23/05/16 06:21, Peter Chen wrote:
> >>>>> On Sat, May 21, 2016 at 10:29:40AM +0800, Peter Chen wrote:
> >>>>>> On Thu, May 19, 2016 at 10:32:44AM +0300, Roger Quadros wrote:
> >>>>>>> On 18/05/16 17:46, Jun Li wrote:
> >>>>>>>>
> >>>>>>>>
> >>>>>>>>>>>
> >>>>>>>>>>> I didn't want to have complex Kconfig so decided to have otg as
> >>>>>>>>>>> built-in only.
> >>>>>>>>>>> What do you want me to change in existing code? and why?
> >>>>>>>>>>
> >>>>>>>>>> Remove those stuff which only for pass diff driver config Like
> >>>>>>>>>> every controller driver need a duplicated
> >>>>>>>>>>
> >>>>>>>>>> static struct otg_hcd_ops ci_hcd_ops = {
> >>>>>>>>>>     ...
> >>>>>>>>>> }
> >>>>>>>>>
> >>>>>>>>> This is an exception only. Every controller driver doesn't need to
> >>>>>>>>> implement hcd_ops. It is implemented in the hcd core.
> >>>>>>>>>
> >>>>>>>>>>
> >>>>>>>>>> And here is another example, for gadget connect, otg driver can
> >>>>>>>>>> directly call to usb_udc_vbus_handler() in drd state machine, but
> >>>>>>>>>> you create another interface:
> >>>>>>>>>>
> >>>>>>>>>> .connect_control = usb_gadget_connect_control,
> >>>>>>>>>>
> >>>>>>>>>> If the symbol is defined in one driver which is 'm', another
> >>>>>>>>>> driver reference it should be 'm' as well, then there is no this
> >>>>>>>>>> kind of problem as my understanding.
> >>>>>>>>>
> >>>>>>>>> That is fine as long as all are 'm'. but how do you solve the case
> >>>>>>>>> when Gadget is built in and host is 'm'? OTG has to be built-in
> >>>>>>>>> and you will need an hcd to gadget interface.
> >>>>>>>>
> >>>>>>>> Hcd to gadget interface? Or you want to say otg to host interface?
> >>>>>>>
> >>>>>>> Sorry, I meant to say host to otg interface.
> >>>>>>>
> >>>>>>>>
> >>>>>>>> I think hcd and gadget are independent each other, now
> >>>>>>>>
> >>>>>>>> Hcd --> otg; and gadget --> otg, (hcd and gadget use otg's symbol)
> >>>>>>>
> >>>>>>> It is actually a circular dependency for both.
> >>>>>>>  hcd <--> otg and gadget <--> otg
> >>>>>>>
> >>>>>>> hcd -> otg for usb_otg_register/unregister_hcd otg -> hcd for
> >>>>>>> usb_add/remove_hcd, usb_bus_start_enum, usb_control_msg,
> >>>>>>> usb_hub_find_child
> >>>>>>>
> >>>>>>> gadget -> otg for usb_otg_register/unregister_gadget
> >>>>>>> otg -> gadget for usb_gadget_start/stop, usb_udc_vbus_handler
> >>>>>>>
> >>>>>>> Now consider what will happen if I get rid of the otg_hcd and
> >>>> otg_gadget interfaces.
> >>>>>>> 'y' means built-in, 'm' means module.
> >>>>>>>
> >>>>>>> 1) hcd 'y', gadget 'y'
> >>>>>>> otg has to be 'y' for proper build.
> >>>>>>>
> >>>>>>> 2) hcd 'm', gadget 'm'
> >>>>>>> otg has to be 'm' for proper build.
> >>>>>>>
> >>>>>>> 3) hcd 'y', gadget 'm'
> >>>>>>> Build will fail always.
> >>>>>>> If otg is 'y', otg build will fail due to dependency on gadget.
> >>>>>>> If otg is 'm', hcd build will fail due to dependency on otg.
> >>>>>>>
> >>>>>>> 4) hcd 'm', gadget 'y'
> >>>>>>> Build will fail always.
> >>>>>>> If otg is 'y', otg build will fail due to dependency on hcd.
> >>>>>>> If otg is 'm', gadget build will fails due to dependency on otg.
> >>>>>>>
> >>>>>>> So I solve this problem by adding the otg_hcd_ops and otg_gadget_ops
> >>>>>>> to remove otg->hcd and otg->gadget dependency.
> >>>>>>>
> >>>>>>> Now we can address 3) and 4) like so
> >>>>>>>
> >>>>>>> 3) hcd 'y', gadget 'm'
> >>>>>>> otg has to be 'y' for proper build.
> >>>>>>>
> >>>>>>> 4) hcd 'm', gadget 'y'
> >>>>>>> otg has to be 'y' for proper build.
> >>>>>>>
> >>>>>>
> >>>>>> How about this:
> >>>>>> Moving usb_otg_register/unregister_hcd to host driver to remove
> >>>>>> dependency hcd->otg. And moving usb_otg_get_data to common.c.
> >>>>>>
> >>>>>> Delete the wait queue at usb-otg.c, and if calling usb_otg_get_data
> >>>>>> returns NULL, the host/device driver's probe return -EPROBE_DEFER.
> >>>>>> When the otg driver is probed successfully, the host/device will be
> >>>>>> re-probed again, and usb_otg_register_hcd will be called again.
> >>>>>>
> >>>>>> And let OTG depends on HCD && GADGET, and delete otg_hcd_ops and
> >>>>>> otg_gadget_ops. Below build dependency issues can be fixed.
> >>>>>> What do you think?
> >>>>>>
> >>>>>>> 1) hcd 'y', gadget 'y'
> >>>>>>> otg has to be 'y' for proper build.
> >>>>>>>
> >>>>>>> 2) hcd 'm', gadget 'm'
> >>>>>>> otg has to be 'm' for proper build.
> >>>>>>>
> >>>>>>> 3) hcd 'y', gadget 'm'
> >>>>>>> Build will fail always.
> >>>>>>> If otg is 'y', otg build will fail due to dependency on gadget.
> >>>>>>> If otg is 'm', hcd build will fail due to dependency on otg.
> >>>>>>>
> >>>>>>> 4) hcd 'm', gadget 'y'
> >>>>>>> Build will fail always.
> >>>>>>> If otg is 'y', otg build will fail due to dependency on hcd.
> >>>>>>> If otg is 'm', gadget build will fails due to dependency on otg.
> >>>>>> --
> >>>>>>
> >>>>>
> >>>>> After thinking more, my suggestion can't work. How about moving
> >>>>> CONFIG_USB_OTG out of CONFIG_USB, in that case, CONFIG_USB_OTG can
> >>>>> only be built in.
> >>>>>
> >>>> I tried this but it still doesn't resolve 3 and 4. I.e.
> >>>> it can't be automatically set to 'y' when either of hcd/gadget is 'y'
> >>>> and the other is 'm'.
> >>>
> >>> USB_OTG only can be selected by *user*, can't be automatically set to
> >>> 'y' like you said, no matter what's hcd/gadget config, USB_OTG can be
> >>> disabled in any cases.
> >>
> >> Yes. I am on the same page with that.
> >>>
> >>> I think Peter's intention is to make USB_OTG to be 'bool', either disabled;
> >>> or built-in(if enabled), something like your original idea?
> >>
> >> I'm fine with my original idea if you guys can confirm :).
> >>
> > 
> > Please do it.
> > 
> 
> OK. I managed to fix this and get usbotg to be as module when both USB and GADGET
> are modules with the following patch.
> 
> What we do is use USB_OTG_CORE as a hidden tristate symbol that is used to build usbotg.o
> only if USB_OTG is enabled.
> 
> USB_OTG is used to enable/disable OTG and it has to be bool since it is used at mutiple
> places in the code.
> 

I am ok with that, but better you can write down above at your commit
log, then the reader can know your design purpose.

Peter
> cheers,
> -roger
> 
> ---
> 
> diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig
> index 8689dcb..ed596ec 100644
> --- a/drivers/usb/Kconfig
> +++ b/drivers/usb/Kconfig
> @@ -32,6 +32,23 @@ if USB_SUPPORT
>  config USB_COMMON
>  	tristate
>  
> +config USB_OTG_CORE
> +	tristate
> +
> +config USB_OTG
> +	bool "OTG/Dual-role support"
> +	depends on PM && USB && USB_GADGET
> +	default n
> +	---help---
> +	  The most notable feature of USB OTG is support for a
> +	  "Dual-Role" device, which can act as either a device
> +	  or a host. The initial role is decided by the type of
> +	  plug inserted and can be changed later when two dual
> +	  role devices talk to each other.
> +
> +	  Select this only if your board has Mini-AB/Micro-AB
> +	  connector.
> +
>  config USB_ARCH_HAS_HCD
>  	def_bool y
>  
> @@ -40,6 +57,7 @@ config USB
>  	tristate "Support for Host-side USB"
>  	depends on USB_ARCH_HAS_HCD
>  	select USB_COMMON
> +	select USB_OTG_CORE
>  	select NLS  # for UTF-8 strings
>  	---help---
>  	  Universal Serial Bus (USB) is a specification for a serial bus
> diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile
> index 16a5b55..03f7204 100644
> --- a/drivers/usb/Makefile
> +++ b/drivers/usb/Makefile
> @@ -59,6 +59,6 @@ obj-$(CONFIG_USB_RENESAS_USBHS)	+= renesas_usbhs/
>  obj-$(CONFIG_USB_GADGET)	+= gadget/
>  
>  obj-$(CONFIG_USB_COMMON)	+= common/
> -obj-$(CONFIG_USB_OTG)		+= common/
> +obj-$(CONFIG_USB_OTG_CORE)	+= common/
>  
>  obj-$(CONFIG_USBIP_CORE)	+= usbip/
> diff --git a/drivers/usb/common/Makefile b/drivers/usb/common/Makefile
> index 730d928..5122b3f 100644
> --- a/drivers/usb/common/Makefile
> +++ b/drivers/usb/common/Makefile
> @@ -7,5 +7,7 @@ usb-common-y			  += common.o
>  usb-common-$(CONFIG_USB_LED_TRIG) += led.o
>  
>  obj-$(CONFIG_USB_ULPI_BUS)	+= ulpi.o
> +ifeq ($(CONFIG_USB_OTG),y)
>  usbotg-y		:= usb-otg.o usb-otg-fsm.o
> -obj-$(CONFIG_USB_OTG)	+= usbotg.o
> +obj-$(CONFIG_USB_OTG_CORE)	+= usbotg.o
> +endif
> diff --git a/drivers/usb/common/usb-otg.c b/drivers/usb/common/usb-otg.c
> index f5eb7f5..98fcfa2 100644
> --- a/drivers/usb/common/usb-otg.c
> +++ b/drivers/usb/common/usb-otg.c
> @@ -16,6 +16,7 @@
>  
>  #include <linux/kernel.h>
>  #include <linux/list.h>
> +#include <linux/module.h>
>  #include <linux/of.h>
>  #include <linux/of_platform.h>
>  #include <linux/usb/of.h>
> @@ -841,3 +842,5 @@ int usb_otg_gadget_ready(struct usb_gadget *gadget, bool ready)
>  	return 0;
>  }
>  EXPORT_SYMBOL_GPL(usb_otg_gadget_ready);
> +
> +MODULE_LICENSE("GPL");
> diff --git a/drivers/usb/core/Kconfig b/drivers/usb/core/Kconfig
> index de371e6..37f8c54 100644
> --- a/drivers/usb/core/Kconfig
> +++ b/drivers/usb/core/Kconfig
> @@ -41,20 +41,6 @@ config USB_DYNAMIC_MINORS
>  
>  	  If you are unsure about this, say N here.
>  
> -config USB_OTG
> -	bool "OTG/Dual-role support"
> -	depends on PM && USB_GADGET
> -	default n
> -	help
> -	  The most notable feature of USB OTG is support for a
> -	  "Dual-Role" device, which can act as either a device
> -	  or a host. The initial role is decided by the type of
> -	  plug inserted and can be changed later when two dual
> -	  role devices talk to each other.
> -
> -	  Select this only if your board has Mini-AB/Micro-AB
> -	  connector.
> -
>  config USB_OTG_WHITELIST
>  	bool "Rely on OTG and EH Targeted Peripherals List"
>  	depends on USB
> diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
> index 2057add..9d55384 100644
> --- a/drivers/usb/gadget/Kconfig
> +++ b/drivers/usb/gadget/Kconfig
> @@ -16,6 +16,7 @@
>  menuconfig USB_GADGET
>  	tristate "USB Gadget Support"
>  	select USB_COMMON
> +	select USB_OTG_CORE
>  	select NLS
>  	help
>  	   USB is a master/slave protocol, organized with one master
> -- 
> 2.7.4
> 
> 
> 

-- 

Best Regards,
Peter Chen

^ permalink raw reply	[flat|nested] 62+ messages in thread

end of thread, other threads:[~2016-06-08  9:11 UTC | newest]

Thread overview: 62+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-05-13 10:03 [PATCH v8 00/14] USB OTG/dual-role framework Roger Quadros
2016-05-13 10:03 ` [PATCH v8 01/14] usb: hcd: Initialize hcd->flags to 0 Roger Quadros
2016-05-13 10:03 ` [PATCH v8 02/14] usb: otg-fsm: Prevent build warning "VDBG" redefined Roger Quadros
2016-05-13 10:03 ` [PATCH v8 03/14] usb: hcd.h: Add OTG to HCD interface Roger Quadros
2016-05-13 10:03 ` [PATCH v8 04/14] usb: otg-fsm: use usb_otg wherever possible Roger Quadros
2016-05-13 10:03 ` [PATCH v8 05/14] usb: otg-fsm: move host controller operations into usb_otg->hcd_ops Roger Quadros
2016-05-13 10:03 ` [PATCH v8 06/14] usb: gadget.h: Add OTG to gadget interface Roger Quadros
2016-05-13 10:03 ` [PATCH v8 07/14] usb: otg: get rid of CONFIG_USB_OTG_FSM in favour of CONFIG_USB_OTG Roger Quadros
2016-05-13 10:03 ` [PATCH v8 08/14] usb: otg: add OTG/dual-role core Roger Quadros
2016-05-16  9:00   ` Roger Quadros
     [not found]     ` <CAL411-qb0dHQrn+AarSApCq6L=toKPRerLKDcx_H+5WDWu_VDg@mail.gmail.com>
2016-05-18 12:59       ` Roger Quadros
2016-05-20  8:31         ` Roger Quadros
2016-05-20  9:19           ` Roger Quadros
2016-05-20  9:53             ` Peter Chen
2016-05-23 10:06               ` Roger Quadros
2016-05-24  9:45   ` Roger Quadros
2016-05-25  2:44     ` Peter Chen
2016-05-25  3:19       ` Jun Li
2016-05-25 12:26         ` Roger Quadros
2016-05-25 12:21       ` Roger Quadros
2016-05-25 14:44         ` Jun Li
2016-05-13 10:03 ` [PATCH v8 09/14] usb: of: add an API to get OTG device from USB controller node Roger Quadros
2016-05-20  9:29   ` [PATCH v9 " Roger Quadros
2016-05-23 21:06     ` Rob Herring
2016-05-13 10:03 ` [PATCH v8 10/14] usb: otg: add hcd companion support Roger Quadros
2016-05-13 18:13   ` Rob Herring
2016-05-16  8:12     ` Roger Quadros
2016-05-20  9:32   ` [PATCH v9 " Roger Quadros
2016-05-23 21:07     ` Rob Herring
2016-05-13 10:03 ` [PATCH v8 11/14] usb: otg: use dev_dbg() instead of VDBG() Roger Quadros
2016-05-13 10:03 ` [PATCH v8 12/14] usb: hcd: Adapt to OTG core Roger Quadros
2016-05-13 10:03 ` [PATCH v8 13/14] usb: gadget: udc: adapt " Roger Quadros
2016-05-16  7:02   ` Peter Chen
2016-05-16  8:26     ` Roger Quadros
2016-05-16  9:23       ` Peter Chen
2016-05-16  9:51         ` Roger Quadros
2016-05-17  7:38           ` Jun Li
2016-05-17  8:08             ` Roger Quadros
2016-05-17  8:28               ` Jun Li
2016-05-18 12:42                 ` Roger Quadros
2016-05-18 13:12                   ` Jun Li
2016-05-18 13:43                     ` Roger Quadros
2016-05-18 14:46                       ` Jun Li
2016-05-19  7:32                         ` Roger Quadros
2016-05-21  2:29                           ` Peter Chen
2016-05-23  3:21                             ` Peter Chen
2016-05-23 10:11                               ` Roger Quadros
2016-05-23 10:34                                 ` Jun Li
2016-05-23 10:36                                   ` Roger Quadros
2016-05-24  2:53                                     ` Peter Chen
2016-06-08  7:32                                       ` Roger Quadros
2016-06-08  9:05                                         ` Peter Chen
2016-05-18  3:18           ` Peter Chen
2016-05-18 12:45             ` Roger Quadros
2016-05-20  1:39               ` Peter Chen
2016-05-20  7:26                 ` Roger Quadros
2016-05-21  2:44                   ` Peter Chen
2016-06-01  7:38   ` Peter Chen
2016-06-02 11:07     ` Roger Quadros
2016-05-13 10:03 ` [PATCH v8 14/14] usb: host: xhci-plat: Add otg device to platform data Roger Quadros
2016-05-30  9:29 ` [PATCH v8 00/14] USB OTG/dual-role framework Peter Chen
2016-05-30 14:04   ` Roger Quadros

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).