xref: /OK3568_Linux_fs/kernel/Documentation/driver-api/usb/writing_musb_glue_layer.rst (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun=========================
2*4882a593SmuzhiyunWriting a MUSB Glue Layer
3*4882a593Smuzhiyun=========================
4*4882a593Smuzhiyun
5*4882a593Smuzhiyun:Author: Apelete Seketeli
6*4882a593Smuzhiyun
7*4882a593SmuzhiyunIntroduction
8*4882a593Smuzhiyun============
9*4882a593Smuzhiyun
10*4882a593SmuzhiyunThe Linux MUSB subsystem is part of the larger Linux USB subsystem. It
11*4882a593Smuzhiyunprovides support for embedded USB Device Controllers (UDC) that do not
12*4882a593Smuzhiyunuse Universal Host Controller Interface (UHCI) or Open Host Controller
13*4882a593SmuzhiyunInterface (OHCI).
14*4882a593Smuzhiyun
15*4882a593SmuzhiyunInstead, these embedded UDC rely on the USB On-the-Go (OTG)
16*4882a593Smuzhiyunspecification which they implement at least partially. The silicon
17*4882a593Smuzhiyunreference design used in most cases is the Multipoint USB Highspeed
18*4882a593SmuzhiyunDual-Role Controller (MUSB HDRC) found in the Mentor Graphics Inventra™
19*4882a593Smuzhiyundesign.
20*4882a593Smuzhiyun
21*4882a593SmuzhiyunAs a self-taught exercise I have written an MUSB glue layer for the
22*4882a593SmuzhiyunIngenic JZ4740 SoC, modelled after the many MUSB glue layers in the
23*4882a593Smuzhiyunkernel source tree. This layer can be found at
24*4882a593Smuzhiyun``drivers/usb/musb/jz4740.c``. In this documentation I will walk through the
25*4882a593Smuzhiyunbasics of the ``jz4740.c`` glue layer, explaining the different pieces and
26*4882a593Smuzhiyunwhat needs to be done in order to write your own device glue layer.
27*4882a593Smuzhiyun
28*4882a593Smuzhiyun.. _musb-basics:
29*4882a593Smuzhiyun
30*4882a593SmuzhiyunLinux MUSB Basics
31*4882a593Smuzhiyun=================
32*4882a593Smuzhiyun
33*4882a593SmuzhiyunTo get started on the topic, please read USB On-the-Go Basics (see
34*4882a593SmuzhiyunResources) which provides an introduction of USB OTG operation at the
35*4882a593Smuzhiyunhardware level. A couple of wiki pages by Texas Instruments and Analog
36*4882a593SmuzhiyunDevices also provide an overview of the Linux kernel MUSB configuration,
37*4882a593Smuzhiyunalbeit focused on some specific devices provided by these companies.
38*4882a593SmuzhiyunFinally, getting acquainted with the USB specification at USB home page
39*4882a593Smuzhiyunmay come in handy, with practical instance provided through the Writing
40*4882a593SmuzhiyunUSB Device Drivers documentation (again, see Resources).
41*4882a593Smuzhiyun
42*4882a593SmuzhiyunLinux USB stack is a layered architecture in which the MUSB controller
43*4882a593Smuzhiyunhardware sits at the lowest. The MUSB controller driver abstract the
44*4882a593SmuzhiyunMUSB controller hardware to the Linux USB stack::
45*4882a593Smuzhiyun
46*4882a593Smuzhiyun	  ------------------------
47*4882a593Smuzhiyun	  |                      | <------- drivers/usb/gadget
48*4882a593Smuzhiyun	  | Linux USB Core Stack | <------- drivers/usb/host
49*4882a593Smuzhiyun	  |                      | <------- drivers/usb/core
50*4882a593Smuzhiyun	  ------------------------
51*4882a593Smuzhiyun52*4882a593Smuzhiyun	 --------------------------
53*4882a593Smuzhiyun	 |                        | <------ drivers/usb/musb/musb_gadget.c
54*4882a593Smuzhiyun	 | MUSB Controller driver | <------ drivers/usb/musb/musb_host.c
55*4882a593Smuzhiyun	 |                        | <------ drivers/usb/musb/musb_core.c
56*4882a593Smuzhiyun	 --------------------------
57*4882a593Smuzhiyun58*4882a593Smuzhiyun      ---------------------------------
59*4882a593Smuzhiyun      | MUSB Platform Specific Driver |
60*4882a593Smuzhiyun      |                               | <-- drivers/usb/musb/jz4740.c
61*4882a593Smuzhiyun      |       aka "Glue Layer"        |
62*4882a593Smuzhiyun      ---------------------------------
63*4882a593Smuzhiyun64*4882a593Smuzhiyun      ---------------------------------
65*4882a593Smuzhiyun      |   MUSB Controller Hardware    |
66*4882a593Smuzhiyun      ---------------------------------
67*4882a593Smuzhiyun
68*4882a593SmuzhiyunAs outlined above, the glue layer is actually the platform specific code
69*4882a593Smuzhiyunsitting in between the controller driver and the controller hardware.
70*4882a593Smuzhiyun
71*4882a593SmuzhiyunJust like a Linux USB driver needs to register itself with the Linux USB
72*4882a593Smuzhiyunsubsystem, the MUSB glue layer needs first to register itself with the
73*4882a593SmuzhiyunMUSB controller driver. This will allow the controller driver to know
74*4882a593Smuzhiyunabout which device the glue layer supports and which functions to call
75*4882a593Smuzhiyunwhen a supported device is detected or released; remember we are talking
76*4882a593Smuzhiyunabout an embedded controller chip here, so no insertion or removal at
77*4882a593Smuzhiyunrun-time.
78*4882a593Smuzhiyun
79*4882a593SmuzhiyunAll of this information is passed to the MUSB controller driver through
80*4882a593Smuzhiyuna :c:type:`platform_driver` structure defined in the glue layer as::
81*4882a593Smuzhiyun
82*4882a593Smuzhiyun    static struct platform_driver jz4740_driver = {
83*4882a593Smuzhiyun	.probe      = jz4740_probe,
84*4882a593Smuzhiyun	.remove     = jz4740_remove,
85*4882a593Smuzhiyun	.driver     = {
86*4882a593Smuzhiyun	    .name   = "musb-jz4740",
87*4882a593Smuzhiyun	},
88*4882a593Smuzhiyun    };
89*4882a593Smuzhiyun
90*4882a593SmuzhiyunThe probe and remove function pointers are called when a matching device
91*4882a593Smuzhiyunis detected and, respectively, released. The name string describes the
92*4882a593Smuzhiyundevice supported by this glue layer. In the current case it matches a
93*4882a593Smuzhiyunplatform_device structure declared in ``arch/mips/jz4740/platform.c``. Note
94*4882a593Smuzhiyunthat we are not using device tree bindings here.
95*4882a593Smuzhiyun
96*4882a593SmuzhiyunIn order to register itself to the controller driver, the glue layer
97*4882a593Smuzhiyungoes through a few steps, basically allocating the controller hardware
98*4882a593Smuzhiyunresources and initialising a couple of circuits. To do so, it needs to
99*4882a593Smuzhiyunkeep track of the information used throughout these steps. This is done
100*4882a593Smuzhiyunby defining a private ``jz4740_glue`` structure::
101*4882a593Smuzhiyun
102*4882a593Smuzhiyun    struct jz4740_glue {
103*4882a593Smuzhiyun	struct device           *dev;
104*4882a593Smuzhiyun	struct platform_device  *musb;
105*4882a593Smuzhiyun	struct clk      *clk;
106*4882a593Smuzhiyun    };
107*4882a593Smuzhiyun
108*4882a593Smuzhiyun
109*4882a593SmuzhiyunThe dev and musb members are both device structure variables. The first
110*4882a593Smuzhiyunone holds generic information about the device, since it's the basic
111*4882a593Smuzhiyundevice structure, and the latter holds information more closely related
112*4882a593Smuzhiyunto the subsystem the device is registered to. The clk variable keeps
113*4882a593Smuzhiyuninformation related to the device clock operation.
114*4882a593Smuzhiyun
115*4882a593SmuzhiyunLet's go through the steps of the probe function that leads the glue
116*4882a593Smuzhiyunlayer to register itself to the controller driver.
117*4882a593Smuzhiyun
118*4882a593Smuzhiyun.. note::
119*4882a593Smuzhiyun
120*4882a593Smuzhiyun   For the sake of readability each function will be split in logical
121*4882a593Smuzhiyun   parts, each part being shown as if it was independent from the others.
122*4882a593Smuzhiyun
123*4882a593Smuzhiyun.. code-block:: c
124*4882a593Smuzhiyun    :emphasize-lines: 8,12,18
125*4882a593Smuzhiyun
126*4882a593Smuzhiyun    static int jz4740_probe(struct platform_device *pdev)
127*4882a593Smuzhiyun    {
128*4882a593Smuzhiyun	struct platform_device      *musb;
129*4882a593Smuzhiyun	struct jz4740_glue      *glue;
130*4882a593Smuzhiyun	struct clk                      *clk;
131*4882a593Smuzhiyun	int             ret;
132*4882a593Smuzhiyun
133*4882a593Smuzhiyun	glue = devm_kzalloc(&pdev->dev, sizeof(*glue), GFP_KERNEL);
134*4882a593Smuzhiyun	if (!glue)
135*4882a593Smuzhiyun	    return -ENOMEM;
136*4882a593Smuzhiyun
137*4882a593Smuzhiyun	musb = platform_device_alloc("musb-hdrc", PLATFORM_DEVID_AUTO);
138*4882a593Smuzhiyun	if (!musb) {
139*4882a593Smuzhiyun	    dev_err(&pdev->dev, "failed to allocate musb device\n");
140*4882a593Smuzhiyun	    return -ENOMEM;
141*4882a593Smuzhiyun	}
142*4882a593Smuzhiyun
143*4882a593Smuzhiyun	clk = devm_clk_get(&pdev->dev, "udc");
144*4882a593Smuzhiyun	if (IS_ERR(clk)) {
145*4882a593Smuzhiyun	    dev_err(&pdev->dev, "failed to get clock\n");
146*4882a593Smuzhiyun	    ret = PTR_ERR(clk);
147*4882a593Smuzhiyun	    goto err_platform_device_put;
148*4882a593Smuzhiyun	}
149*4882a593Smuzhiyun
150*4882a593Smuzhiyun	ret = clk_prepare_enable(clk);
151*4882a593Smuzhiyun	if (ret) {
152*4882a593Smuzhiyun	    dev_err(&pdev->dev, "failed to enable clock\n");
153*4882a593Smuzhiyun	    goto err_platform_device_put;
154*4882a593Smuzhiyun	}
155*4882a593Smuzhiyun
156*4882a593Smuzhiyun	musb->dev.parent        = &pdev->dev;
157*4882a593Smuzhiyun
158*4882a593Smuzhiyun	glue->dev           = &pdev->dev;
159*4882a593Smuzhiyun	glue->musb          = musb;
160*4882a593Smuzhiyun	glue->clk           = clk;
161*4882a593Smuzhiyun
162*4882a593Smuzhiyun	return 0;
163*4882a593Smuzhiyun
164*4882a593Smuzhiyun    err_platform_device_put:
165*4882a593Smuzhiyun	platform_device_put(musb);
166*4882a593Smuzhiyun	return ret;
167*4882a593Smuzhiyun    }
168*4882a593Smuzhiyun
169*4882a593SmuzhiyunThe first few lines of the probe function allocate and assign the glue,
170*4882a593Smuzhiyunmusb and clk variables. The ``GFP_KERNEL`` flag (line 8) allows the
171*4882a593Smuzhiyunallocation process to sleep and wait for memory, thus being usable in a
172*4882a593Smuzhiyunlocking situation. The ``PLATFORM_DEVID_AUTO`` flag (line 12) allows
173*4882a593Smuzhiyunautomatic allocation and management of device IDs in order to avoid
174*4882a593Smuzhiyundevice namespace collisions with explicit IDs. With :c:func:`devm_clk_get`
175*4882a593Smuzhiyun(line 18) the glue layer allocates the clock -- the ``devm_`` prefix
176*4882a593Smuzhiyunindicates that :c:func:`clk_get` is managed: it automatically frees the
177*4882a593Smuzhiyunallocated clock resource data when the device is released -- and enable
178*4882a593Smuzhiyunit.
179*4882a593Smuzhiyun
180*4882a593Smuzhiyun
181*4882a593Smuzhiyun
182*4882a593SmuzhiyunThen comes the registration steps:
183*4882a593Smuzhiyun
184*4882a593Smuzhiyun.. code-block:: c
185*4882a593Smuzhiyun    :emphasize-lines: 3,5,7,9,16
186*4882a593Smuzhiyun
187*4882a593Smuzhiyun    static int jz4740_probe(struct platform_device *pdev)
188*4882a593Smuzhiyun    {
189*4882a593Smuzhiyun	struct musb_hdrc_platform_data  *pdata = &jz4740_musb_platform_data;
190*4882a593Smuzhiyun
191*4882a593Smuzhiyun	pdata->platform_ops     = &jz4740_musb_ops;
192*4882a593Smuzhiyun
193*4882a593Smuzhiyun	platform_set_drvdata(pdev, glue);
194*4882a593Smuzhiyun
195*4882a593Smuzhiyun	ret = platform_device_add_resources(musb, pdev->resource,
196*4882a593Smuzhiyun			    pdev->num_resources);
197*4882a593Smuzhiyun	if (ret) {
198*4882a593Smuzhiyun	    dev_err(&pdev->dev, "failed to add resources\n");
199*4882a593Smuzhiyun	    goto err_clk_disable;
200*4882a593Smuzhiyun	}
201*4882a593Smuzhiyun
202*4882a593Smuzhiyun	ret = platform_device_add_data(musb, pdata, sizeof(*pdata));
203*4882a593Smuzhiyun	if (ret) {
204*4882a593Smuzhiyun	    dev_err(&pdev->dev, "failed to add platform_data\n");
205*4882a593Smuzhiyun	    goto err_clk_disable;
206*4882a593Smuzhiyun	}
207*4882a593Smuzhiyun
208*4882a593Smuzhiyun	return 0;
209*4882a593Smuzhiyun
210*4882a593Smuzhiyun    err_clk_disable:
211*4882a593Smuzhiyun	clk_disable_unprepare(clk);
212*4882a593Smuzhiyun    err_platform_device_put:
213*4882a593Smuzhiyun	platform_device_put(musb);
214*4882a593Smuzhiyun	return ret;
215*4882a593Smuzhiyun    }
216*4882a593Smuzhiyun
217*4882a593SmuzhiyunThe first step is to pass the device data privately held by the glue
218*4882a593Smuzhiyunlayer on to the controller driver through :c:func:`platform_set_drvdata`
219*4882a593Smuzhiyun(line 7). Next is passing on the device resources information, also privately
220*4882a593Smuzhiyunheld at that point, through :c:func:`platform_device_add_resources` (line 9).
221*4882a593Smuzhiyun
222*4882a593SmuzhiyunFinally comes passing on the platform specific data to the controller
223*4882a593Smuzhiyundriver (line 16). Platform data will be discussed in
224*4882a593Smuzhiyun:ref:`musb-dev-platform-data`, but here we are looking at the
225*4882a593Smuzhiyun``platform_ops`` function pointer (line 5) in ``musb_hdrc_platform_data``
226*4882a593Smuzhiyunstructure (line 3). This function pointer allows the MUSB controller
227*4882a593Smuzhiyundriver to know which function to call for device operation::
228*4882a593Smuzhiyun
229*4882a593Smuzhiyun    static const struct musb_platform_ops jz4740_musb_ops = {
230*4882a593Smuzhiyun	.init       = jz4740_musb_init,
231*4882a593Smuzhiyun	.exit       = jz4740_musb_exit,
232*4882a593Smuzhiyun    };
233*4882a593Smuzhiyun
234*4882a593SmuzhiyunHere we have the minimal case where only init and exit functions are
235*4882a593Smuzhiyuncalled by the controller driver when needed. Fact is the JZ4740 MUSB
236*4882a593Smuzhiyuncontroller is a basic controller, lacking some features found in other
237*4882a593Smuzhiyuncontrollers, otherwise we may also have pointers to a few other
238*4882a593Smuzhiyunfunctions like a power management function or a function to switch
239*4882a593Smuzhiyunbetween OTG and non-OTG modes, for instance.
240*4882a593Smuzhiyun
241*4882a593SmuzhiyunAt that point of the registration process, the controller driver
242*4882a593Smuzhiyunactually calls the init function:
243*4882a593Smuzhiyun
244*4882a593Smuzhiyun   .. code-block:: c
245*4882a593Smuzhiyun    :emphasize-lines: 12,14
246*4882a593Smuzhiyun
247*4882a593Smuzhiyun    static int jz4740_musb_init(struct musb *musb)
248*4882a593Smuzhiyun    {
249*4882a593Smuzhiyun	musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2);
250*4882a593Smuzhiyun	if (!musb->xceiv) {
251*4882a593Smuzhiyun	    pr_err("HS UDC: no transceiver configured\n");
252*4882a593Smuzhiyun	    return -ENODEV;
253*4882a593Smuzhiyun	}
254*4882a593Smuzhiyun
255*4882a593Smuzhiyun	/* Silicon does not implement ConfigData register.
256*4882a593Smuzhiyun	 * Set dyn_fifo to avoid reading EP config from hardware.
257*4882a593Smuzhiyun	 */
258*4882a593Smuzhiyun	musb->dyn_fifo = true;
259*4882a593Smuzhiyun
260*4882a593Smuzhiyun	musb->isr = jz4740_musb_interrupt;
261*4882a593Smuzhiyun
262*4882a593Smuzhiyun	return 0;
263*4882a593Smuzhiyun    }
264*4882a593Smuzhiyun
265*4882a593SmuzhiyunThe goal of ``jz4740_musb_init()`` is to get hold of the transceiver
266*4882a593Smuzhiyundriver data of the MUSB controller hardware and pass it on to the MUSB
267*4882a593Smuzhiyuncontroller driver, as usual. The transceiver is the circuitry inside the
268*4882a593Smuzhiyuncontroller hardware responsible for sending/receiving the USB data.
269*4882a593SmuzhiyunSince it is an implementation of the physical layer of the OSI model,
270*4882a593Smuzhiyunthe transceiver is also referred to as PHY.
271*4882a593Smuzhiyun
272*4882a593SmuzhiyunGetting hold of the ``MUSB PHY`` driver data is done with ``usb_get_phy()``
273*4882a593Smuzhiyunwhich returns a pointer to the structure containing the driver instance
274*4882a593Smuzhiyundata. The next couple of instructions (line 12 and 14) are used as a
275*4882a593Smuzhiyunquirk and to setup IRQ handling respectively. Quirks and IRQ handling
276*4882a593Smuzhiyunwill be discussed later in :ref:`musb-dev-quirks` and
277*4882a593Smuzhiyun:ref:`musb-handling-irqs`\ ::
278*4882a593Smuzhiyun
279*4882a593Smuzhiyun    static int jz4740_musb_exit(struct musb *musb)
280*4882a593Smuzhiyun    {
281*4882a593Smuzhiyun	usb_put_phy(musb->xceiv);
282*4882a593Smuzhiyun
283*4882a593Smuzhiyun	return 0;
284*4882a593Smuzhiyun    }
285*4882a593Smuzhiyun
286*4882a593SmuzhiyunActing as the counterpart of init, the exit function releases the MUSB
287*4882a593SmuzhiyunPHY driver when the controller hardware itself is about to be released.
288*4882a593Smuzhiyun
289*4882a593SmuzhiyunAgain, note that init and exit are fairly simple in this case due to the
290*4882a593Smuzhiyunbasic set of features of the JZ4740 controller hardware. When writing an
291*4882a593Smuzhiyunmusb glue layer for a more complex controller hardware, you might need
292*4882a593Smuzhiyunto take care of more processing in those two functions.
293*4882a593Smuzhiyun
294*4882a593SmuzhiyunReturning from the init function, the MUSB controller driver jumps back
295*4882a593Smuzhiyuninto the probe function::
296*4882a593Smuzhiyun
297*4882a593Smuzhiyun    static int jz4740_probe(struct platform_device *pdev)
298*4882a593Smuzhiyun    {
299*4882a593Smuzhiyun	ret = platform_device_add(musb);
300*4882a593Smuzhiyun	if (ret) {
301*4882a593Smuzhiyun	    dev_err(&pdev->dev, "failed to register musb device\n");
302*4882a593Smuzhiyun	    goto err_clk_disable;
303*4882a593Smuzhiyun	}
304*4882a593Smuzhiyun
305*4882a593Smuzhiyun	return 0;
306*4882a593Smuzhiyun
307*4882a593Smuzhiyun    err_clk_disable:
308*4882a593Smuzhiyun	clk_disable_unprepare(clk);
309*4882a593Smuzhiyun    err_platform_device_put:
310*4882a593Smuzhiyun	platform_device_put(musb);
311*4882a593Smuzhiyun	return ret;
312*4882a593Smuzhiyun    }
313*4882a593Smuzhiyun
314*4882a593SmuzhiyunThis is the last part of the device registration process where the glue
315*4882a593Smuzhiyunlayer adds the controller hardware device to Linux kernel device
316*4882a593Smuzhiyunhierarchy: at this stage, all known information about the device is
317*4882a593Smuzhiyunpassed on to the Linux USB core stack:
318*4882a593Smuzhiyun
319*4882a593Smuzhiyun   .. code-block:: c
320*4882a593Smuzhiyun    :emphasize-lines: 5,6
321*4882a593Smuzhiyun
322*4882a593Smuzhiyun    static int jz4740_remove(struct platform_device *pdev)
323*4882a593Smuzhiyun    {
324*4882a593Smuzhiyun	struct jz4740_glue  *glue = platform_get_drvdata(pdev);
325*4882a593Smuzhiyun
326*4882a593Smuzhiyun	platform_device_unregister(glue->musb);
327*4882a593Smuzhiyun	clk_disable_unprepare(glue->clk);
328*4882a593Smuzhiyun
329*4882a593Smuzhiyun	return 0;
330*4882a593Smuzhiyun    }
331*4882a593Smuzhiyun
332*4882a593SmuzhiyunActing as the counterpart of probe, the remove function unregister the
333*4882a593SmuzhiyunMUSB controller hardware (line 5) and disable the clock (line 6),
334*4882a593Smuzhiyunallowing it to be gated.
335*4882a593Smuzhiyun
336*4882a593Smuzhiyun.. _musb-handling-irqs:
337*4882a593Smuzhiyun
338*4882a593SmuzhiyunHandling IRQs
339*4882a593Smuzhiyun=============
340*4882a593Smuzhiyun
341*4882a593SmuzhiyunAdditionally to the MUSB controller hardware basic setup and
342*4882a593Smuzhiyunregistration, the glue layer is also responsible for handling the IRQs:
343*4882a593Smuzhiyun
344*4882a593Smuzhiyun   .. code-block:: c
345*4882a593Smuzhiyun    :emphasize-lines: 7,9-11,14,24
346*4882a593Smuzhiyun
347*4882a593Smuzhiyun    static irqreturn_t jz4740_musb_interrupt(int irq, void *__hci)
348*4882a593Smuzhiyun    {
349*4882a593Smuzhiyun	unsigned long   flags;
350*4882a593Smuzhiyun	irqreturn_t     retval = IRQ_NONE;
351*4882a593Smuzhiyun	struct musb     *musb = __hci;
352*4882a593Smuzhiyun
353*4882a593Smuzhiyun	spin_lock_irqsave(&musb->lock, flags);
354*4882a593Smuzhiyun
355*4882a593Smuzhiyun	musb->int_usb = musb_readb(musb->mregs, MUSB_INTRUSB);
356*4882a593Smuzhiyun	musb->int_tx = musb_readw(musb->mregs, MUSB_INTRTX);
357*4882a593Smuzhiyun	musb->int_rx = musb_readw(musb->mregs, MUSB_INTRRX);
358*4882a593Smuzhiyun
359*4882a593Smuzhiyun	/*
360*4882a593Smuzhiyun	 * The controller is gadget only, the state of the host mode IRQ bits is
361*4882a593Smuzhiyun	 * undefined. Mask them to make sure that the musb driver core will
362*4882a593Smuzhiyun	 * never see them set
363*4882a593Smuzhiyun	 */
364*4882a593Smuzhiyun	musb->int_usb &= MUSB_INTR_SUSPEND | MUSB_INTR_RESUME |
365*4882a593Smuzhiyun	    MUSB_INTR_RESET | MUSB_INTR_SOF;
366*4882a593Smuzhiyun
367*4882a593Smuzhiyun	if (musb->int_usb || musb->int_tx || musb->int_rx)
368*4882a593Smuzhiyun	    retval = musb_interrupt(musb);
369*4882a593Smuzhiyun
370*4882a593Smuzhiyun	spin_unlock_irqrestore(&musb->lock, flags);
371*4882a593Smuzhiyun
372*4882a593Smuzhiyun	return retval;
373*4882a593Smuzhiyun    }
374*4882a593Smuzhiyun
375*4882a593SmuzhiyunHere the glue layer mostly has to read the relevant hardware registers
376*4882a593Smuzhiyunand pass their values on to the controller driver which will handle the
377*4882a593Smuzhiyunactual event that triggered the IRQ.
378*4882a593Smuzhiyun
379*4882a593SmuzhiyunThe interrupt handler critical section is protected by the
380*4882a593Smuzhiyun:c:func:`spin_lock_irqsave` and counterpart :c:func:`spin_unlock_irqrestore`
381*4882a593Smuzhiyunfunctions (line 7 and 24 respectively), which prevent the interrupt
382*4882a593Smuzhiyunhandler code to be run by two different threads at the same time.
383*4882a593Smuzhiyun
384*4882a593SmuzhiyunThen the relevant interrupt registers are read (line 9 to 11):
385*4882a593Smuzhiyun
386*4882a593Smuzhiyun-  ``MUSB_INTRUSB``: indicates which USB interrupts are currently active,
387*4882a593Smuzhiyun
388*4882a593Smuzhiyun-  ``MUSB_INTRTX``: indicates which of the interrupts for TX endpoints are
389*4882a593Smuzhiyun   currently active,
390*4882a593Smuzhiyun
391*4882a593Smuzhiyun-  ``MUSB_INTRRX``: indicates which of the interrupts for TX endpoints are
392*4882a593Smuzhiyun   currently active.
393*4882a593Smuzhiyun
394*4882a593SmuzhiyunNote that :c:func:`musb_readb` is used to read 8-bit registers at most, while
395*4882a593Smuzhiyun:c:func:`musb_readw` allows us to read at most 16-bit registers. There are
396*4882a593Smuzhiyunother functions that can be used depending on the size of your device
397*4882a593Smuzhiyunregisters. See ``musb_io.h`` for more information.
398*4882a593Smuzhiyun
399*4882a593SmuzhiyunInstruction on line 18 is another quirk specific to the JZ4740 USB
400*4882a593Smuzhiyundevice controller, which will be discussed later in :ref:`musb-dev-quirks`.
401*4882a593Smuzhiyun
402*4882a593SmuzhiyunThe glue layer still needs to register the IRQ handler though. Remember
403*4882a593Smuzhiyunthe instruction on line 14 of the init function::
404*4882a593Smuzhiyun
405*4882a593Smuzhiyun    static int jz4740_musb_init(struct musb *musb)
406*4882a593Smuzhiyun    {
407*4882a593Smuzhiyun	musb->isr = jz4740_musb_interrupt;
408*4882a593Smuzhiyun
409*4882a593Smuzhiyun	return 0;
410*4882a593Smuzhiyun    }
411*4882a593Smuzhiyun
412*4882a593SmuzhiyunThis instruction sets a pointer to the glue layer IRQ handler function,
413*4882a593Smuzhiyunin order for the controller hardware to call the handler back when an
414*4882a593SmuzhiyunIRQ comes from the controller hardware. The interrupt handler is now
415*4882a593Smuzhiyunimplemented and registered.
416*4882a593Smuzhiyun
417*4882a593Smuzhiyun.. _musb-dev-platform-data:
418*4882a593Smuzhiyun
419*4882a593SmuzhiyunDevice Platform Data
420*4882a593Smuzhiyun====================
421*4882a593Smuzhiyun
422*4882a593SmuzhiyunIn order to write an MUSB glue layer, you need to have some data
423*4882a593Smuzhiyundescribing the hardware capabilities of your controller hardware, which
424*4882a593Smuzhiyunis called the platform data.
425*4882a593Smuzhiyun
426*4882a593SmuzhiyunPlatform data is specific to your hardware, though it may cover a broad
427*4882a593Smuzhiyunrange of devices, and is generally found somewhere in the ``arch/``
428*4882a593Smuzhiyundirectory, depending on your device architecture.
429*4882a593Smuzhiyun
430*4882a593SmuzhiyunFor instance, platform data for the JZ4740 SoC is found in
431*4882a593Smuzhiyun``arch/mips/jz4740/platform.c``. In the ``platform.c`` file each device of the
432*4882a593SmuzhiyunJZ4740 SoC is described through a set of structures.
433*4882a593Smuzhiyun
434*4882a593SmuzhiyunHere is the part of ``arch/mips/jz4740/platform.c`` that covers the USB
435*4882a593SmuzhiyunDevice Controller (UDC):
436*4882a593Smuzhiyun
437*4882a593Smuzhiyun   .. code-block:: c
438*4882a593Smuzhiyun    :emphasize-lines: 2,7,14-17,21,22,25,26,28,29
439*4882a593Smuzhiyun
440*4882a593Smuzhiyun    /* USB Device Controller */
441*4882a593Smuzhiyun    struct platform_device jz4740_udc_xceiv_device = {
442*4882a593Smuzhiyun	.name = "usb_phy_gen_xceiv",
443*4882a593Smuzhiyun	.id   = 0,
444*4882a593Smuzhiyun    };
445*4882a593Smuzhiyun
446*4882a593Smuzhiyun    static struct resource jz4740_udc_resources[] = {
447*4882a593Smuzhiyun	[0] = {
448*4882a593Smuzhiyun	    .start = JZ4740_UDC_BASE_ADDR,
449*4882a593Smuzhiyun	    .end   = JZ4740_UDC_BASE_ADDR + 0x10000 - 1,
450*4882a593Smuzhiyun	    .flags = IORESOURCE_MEM,
451*4882a593Smuzhiyun	},
452*4882a593Smuzhiyun	[1] = {
453*4882a593Smuzhiyun	    .start = JZ4740_IRQ_UDC,
454*4882a593Smuzhiyun	    .end   = JZ4740_IRQ_UDC,
455*4882a593Smuzhiyun	    .flags = IORESOURCE_IRQ,
456*4882a593Smuzhiyun	    .name  = "mc",
457*4882a593Smuzhiyun	},
458*4882a593Smuzhiyun    };
459*4882a593Smuzhiyun
460*4882a593Smuzhiyun    struct platform_device jz4740_udc_device = {
461*4882a593Smuzhiyun	.name = "musb-jz4740",
462*4882a593Smuzhiyun	.id   = -1,
463*4882a593Smuzhiyun	.dev  = {
464*4882a593Smuzhiyun	    .dma_mask          = &jz4740_udc_device.dev.coherent_dma_mask,
465*4882a593Smuzhiyun	    .coherent_dma_mask = DMA_BIT_MASK(32),
466*4882a593Smuzhiyun	},
467*4882a593Smuzhiyun	.num_resources = ARRAY_SIZE(jz4740_udc_resources),
468*4882a593Smuzhiyun	.resource      = jz4740_udc_resources,
469*4882a593Smuzhiyun    };
470*4882a593Smuzhiyun
471*4882a593SmuzhiyunThe ``jz4740_udc_xceiv_device`` platform device structure (line 2)
472*4882a593Smuzhiyundescribes the UDC transceiver with a name and id number.
473*4882a593Smuzhiyun
474*4882a593SmuzhiyunAt the time of this writing, note that ``usb_phy_gen_xceiv`` is the
475*4882a593Smuzhiyunspecific name to be used for all transceivers that are either built-in
476*4882a593Smuzhiyunwith reference USB IP or autonomous and doesn't require any PHY
477*4882a593Smuzhiyunprogramming. You will need to set ``CONFIG_NOP_USB_XCEIV=y`` in the
478*4882a593Smuzhiyunkernel configuration to make use of the corresponding transceiver
479*4882a593Smuzhiyundriver. The id field could be set to -1 (equivalent to
480*4882a593Smuzhiyun``PLATFORM_DEVID_NONE``), -2 (equivalent to ``PLATFORM_DEVID_AUTO``) or
481*4882a593Smuzhiyunstart with 0 for the first device of this kind if we want a specific id
482*4882a593Smuzhiyunnumber.
483*4882a593Smuzhiyun
484*4882a593SmuzhiyunThe ``jz4740_udc_resources`` resource structure (line 7) defines the UDC
485*4882a593Smuzhiyunregisters base addresses.
486*4882a593Smuzhiyun
487*4882a593SmuzhiyunThe first array (line 9 to 11) defines the UDC registers base memory
488*4882a593Smuzhiyunaddresses: start points to the first register memory address, end points
489*4882a593Smuzhiyunto the last register memory address and the flags member defines the
490*4882a593Smuzhiyuntype of resource we are dealing with. So ``IORESOURCE_MEM`` is used to
491*4882a593Smuzhiyundefine the registers memory addresses. The second array (line 14 to 17)
492*4882a593Smuzhiyundefines the UDC IRQ registers addresses. Since there is only one IRQ
493*4882a593Smuzhiyunregister available for the JZ4740 UDC, start and end point at the same
494*4882a593Smuzhiyunaddress. The ``IORESOURCE_IRQ`` flag tells that we are dealing with IRQ
495*4882a593Smuzhiyunresources, and the name ``mc`` is in fact hard-coded in the MUSB core in
496*4882a593Smuzhiyunorder for the controller driver to retrieve this IRQ resource by
497*4882a593Smuzhiyunquerying it by its name.
498*4882a593Smuzhiyun
499*4882a593SmuzhiyunFinally, the ``jz4740_udc_device`` platform device structure (line 21)
500*4882a593Smuzhiyundescribes the UDC itself.
501*4882a593Smuzhiyun
502*4882a593SmuzhiyunThe ``musb-jz4740`` name (line 22) defines the MUSB driver that is used
503*4882a593Smuzhiyunfor this device; remember this is in fact the name that we used in the
504*4882a593Smuzhiyun``jz4740_driver`` platform driver structure in :ref:`musb-basics`.
505*4882a593SmuzhiyunThe id field (line 23) is set to -1 (equivalent to ``PLATFORM_DEVID_NONE``)
506*4882a593Smuzhiyunsince we do not need an id for the device: the MUSB controller driver was
507*4882a593Smuzhiyunalready set to allocate an automatic id in :ref:`musb-basics`. In the dev field
508*4882a593Smuzhiyunwe care for DMA related information here. The ``dma_mask`` field (line 25)
509*4882a593Smuzhiyundefines the width of the DMA mask that is going to be used, and
510*4882a593Smuzhiyun``coherent_dma_mask`` (line 26) has the same purpose but for the
511*4882a593Smuzhiyun``alloc_coherent`` DMA mappings: in both cases we are using a 32 bits mask.
512*4882a593SmuzhiyunThen the resource field (line 29) is simply a pointer to the resource
513*4882a593Smuzhiyunstructure defined before, while the ``num_resources`` field (line 28) keeps
514*4882a593Smuzhiyuntrack of the number of arrays defined in the resource structure (in this
515*4882a593Smuzhiyuncase there were two resource arrays defined before).
516*4882a593Smuzhiyun
517*4882a593SmuzhiyunWith this quick overview of the UDC platform data at the ``arch/`` level now
518*4882a593Smuzhiyundone, let's get back to the MUSB glue layer specific platform data in
519*4882a593Smuzhiyun``drivers/usb/musb/jz4740.c``:
520*4882a593Smuzhiyun
521*4882a593Smuzhiyun   .. code-block:: c
522*4882a593Smuzhiyun    :emphasize-lines: 3,5,7-9,11
523*4882a593Smuzhiyun
524*4882a593Smuzhiyun    static struct musb_hdrc_config jz4740_musb_config = {
525*4882a593Smuzhiyun	/* Silicon does not implement USB OTG. */
526*4882a593Smuzhiyun	.multipoint = 0,
527*4882a593Smuzhiyun	/* Max EPs scanned, driver will decide which EP can be used. */
528*4882a593Smuzhiyun	.num_eps    = 4,
529*4882a593Smuzhiyun	/* RAMbits needed to configure EPs from table */
530*4882a593Smuzhiyun	.ram_bits   = 9,
531*4882a593Smuzhiyun	.fifo_cfg = jz4740_musb_fifo_cfg,
532*4882a593Smuzhiyun	.fifo_cfg_size = ARRAY_SIZE(jz4740_musb_fifo_cfg),
533*4882a593Smuzhiyun    };
534*4882a593Smuzhiyun
535*4882a593Smuzhiyun    static struct musb_hdrc_platform_data jz4740_musb_platform_data = {
536*4882a593Smuzhiyun	.mode   = MUSB_PERIPHERAL,
537*4882a593Smuzhiyun	.config = &jz4740_musb_config,
538*4882a593Smuzhiyun    };
539*4882a593Smuzhiyun
540*4882a593SmuzhiyunFirst the glue layer configures some aspects of the controller driver
541*4882a593Smuzhiyunoperation related to the controller hardware specifics. This is done
542*4882a593Smuzhiyunthrough the ``jz4740_musb_config`` :c:type:`musb_hdrc_config` structure.
543*4882a593Smuzhiyun
544*4882a593SmuzhiyunDefining the OTG capability of the controller hardware, the multipoint
545*4882a593Smuzhiyunmember (line 3) is set to 0 (equivalent to false) since the JZ4740 UDC
546*4882a593Smuzhiyunis not OTG compatible. Then ``num_eps`` (line 5) defines the number of USB
547*4882a593Smuzhiyunendpoints of the controller hardware, including endpoint 0: here we have
548*4882a593Smuzhiyun3 endpoints + endpoint 0. Next is ``ram_bits`` (line 7) which is the width
549*4882a593Smuzhiyunof the RAM address bus for the MUSB controller hardware. This
550*4882a593Smuzhiyuninformation is needed when the controller driver cannot automatically
551*4882a593Smuzhiyunconfigure endpoints by reading the relevant controller hardware
552*4882a593Smuzhiyunregisters. This issue will be discussed when we get to device quirks in
553*4882a593Smuzhiyun:ref:`musb-dev-quirks`. Last two fields (line 8 and 9) are also
554*4882a593Smuzhiyunabout device quirks: ``fifo_cfg`` points to the USB endpoints configuration
555*4882a593Smuzhiyuntable and ``fifo_cfg_size`` keeps track of the size of the number of
556*4882a593Smuzhiyunentries in that configuration table. More on that later in
557*4882a593Smuzhiyun:ref:`musb-dev-quirks`.
558*4882a593Smuzhiyun
559*4882a593SmuzhiyunThen this configuration is embedded inside ``jz4740_musb_platform_data``
560*4882a593Smuzhiyun:c:type:`musb_hdrc_platform_data` structure (line 11): config is a pointer to
561*4882a593Smuzhiyunthe configuration structure itself, and mode tells the controller driver
562*4882a593Smuzhiyunif the controller hardware may be used as ``MUSB_HOST`` only,
563*4882a593Smuzhiyun``MUSB_PERIPHERAL`` only or ``MUSB_OTG`` which is a dual mode.
564*4882a593Smuzhiyun
565*4882a593SmuzhiyunRemember that ``jz4740_musb_platform_data`` is then used to convey
566*4882a593Smuzhiyunplatform data information as we have seen in the probe function in
567*4882a593Smuzhiyun:ref:`musb-basics`.
568*4882a593Smuzhiyun
569*4882a593Smuzhiyun.. _musb-dev-quirks:
570*4882a593Smuzhiyun
571*4882a593SmuzhiyunDevice Quirks
572*4882a593Smuzhiyun=============
573*4882a593Smuzhiyun
574*4882a593SmuzhiyunCompleting the platform data specific to your device, you may also need
575*4882a593Smuzhiyunto write some code in the glue layer to work around some device specific
576*4882a593Smuzhiyunlimitations. These quirks may be due to some hardware bugs, or simply be
577*4882a593Smuzhiyunthe result of an incomplete implementation of the USB On-the-Go
578*4882a593Smuzhiyunspecification.
579*4882a593Smuzhiyun
580*4882a593SmuzhiyunThe JZ4740 UDC exhibits such quirks, some of which we will discuss here
581*4882a593Smuzhiyunfor the sake of insight even though these might not be found in the
582*4882a593Smuzhiyuncontroller hardware you are working on.
583*4882a593Smuzhiyun
584*4882a593SmuzhiyunLet's get back to the init function first:
585*4882a593Smuzhiyun
586*4882a593Smuzhiyun   .. code-block:: c
587*4882a593Smuzhiyun    :emphasize-lines: 12
588*4882a593Smuzhiyun
589*4882a593Smuzhiyun    static int jz4740_musb_init(struct musb *musb)
590*4882a593Smuzhiyun    {
591*4882a593Smuzhiyun	musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2);
592*4882a593Smuzhiyun	if (!musb->xceiv) {
593*4882a593Smuzhiyun	    pr_err("HS UDC: no transceiver configured\n");
594*4882a593Smuzhiyun	    return -ENODEV;
595*4882a593Smuzhiyun	}
596*4882a593Smuzhiyun
597*4882a593Smuzhiyun	/* Silicon does not implement ConfigData register.
598*4882a593Smuzhiyun	 * Set dyn_fifo to avoid reading EP config from hardware.
599*4882a593Smuzhiyun	 */
600*4882a593Smuzhiyun	musb->dyn_fifo = true;
601*4882a593Smuzhiyun
602*4882a593Smuzhiyun	musb->isr = jz4740_musb_interrupt;
603*4882a593Smuzhiyun
604*4882a593Smuzhiyun	return 0;
605*4882a593Smuzhiyun    }
606*4882a593Smuzhiyun
607*4882a593SmuzhiyunInstruction on line 12 helps the MUSB controller driver to work around
608*4882a593Smuzhiyunthe fact that the controller hardware is missing registers that are used
609*4882a593Smuzhiyunfor USB endpoints configuration.
610*4882a593Smuzhiyun
611*4882a593SmuzhiyunWithout these registers, the controller driver is unable to read the
612*4882a593Smuzhiyunendpoints configuration from the hardware, so we use line 12 instruction
613*4882a593Smuzhiyunto bypass reading the configuration from silicon, and rely on a
614*4882a593Smuzhiyunhard-coded table that describes the endpoints configuration instead::
615*4882a593Smuzhiyun
616*4882a593Smuzhiyun    static struct musb_fifo_cfg jz4740_musb_fifo_cfg[] = {
617*4882a593Smuzhiyun	{ .hw_ep_num = 1, .style = FIFO_TX, .maxpacket = 512, },
618*4882a593Smuzhiyun	{ .hw_ep_num = 1, .style = FIFO_RX, .maxpacket = 512, },
619*4882a593Smuzhiyun	{ .hw_ep_num = 2, .style = FIFO_TX, .maxpacket = 64, },
620*4882a593Smuzhiyun    };
621*4882a593Smuzhiyun
622*4882a593SmuzhiyunLooking at the configuration table above, we see that each endpoints is
623*4882a593Smuzhiyundescribed by three fields: ``hw_ep_num`` is the endpoint number, style is
624*4882a593Smuzhiyunits direction (either ``FIFO_TX`` for the controller driver to send packets
625*4882a593Smuzhiyunin the controller hardware, or ``FIFO_RX`` to receive packets from
626*4882a593Smuzhiyunhardware), and maxpacket defines the maximum size of each data packet
627*4882a593Smuzhiyunthat can be transmitted over that endpoint. Reading from the table, the
628*4882a593Smuzhiyuncontroller driver knows that endpoint 1 can be used to send and receive
629*4882a593SmuzhiyunUSB data packets of 512 bytes at once (this is in fact a bulk in/out
630*4882a593Smuzhiyunendpoint), and endpoint 2 can be used to send data packets of 64 bytes
631*4882a593Smuzhiyunat once (this is in fact an interrupt endpoint).
632*4882a593Smuzhiyun
633*4882a593SmuzhiyunNote that there is no information about endpoint 0 here: that one is
634*4882a593Smuzhiyunimplemented by default in every silicon design, with a predefined
635*4882a593Smuzhiyunconfiguration according to the USB specification. For more examples of
636*4882a593Smuzhiyunendpoint configuration tables, see ``musb_core.c``.
637*4882a593Smuzhiyun
638*4882a593SmuzhiyunLet's now get back to the interrupt handler function:
639*4882a593Smuzhiyun
640*4882a593Smuzhiyun   .. code-block:: c
641*4882a593Smuzhiyun    :emphasize-lines: 18-19
642*4882a593Smuzhiyun
643*4882a593Smuzhiyun    static irqreturn_t jz4740_musb_interrupt(int irq, void *__hci)
644*4882a593Smuzhiyun    {
645*4882a593Smuzhiyun	unsigned long   flags;
646*4882a593Smuzhiyun	irqreturn_t     retval = IRQ_NONE;
647*4882a593Smuzhiyun	struct musb     *musb = __hci;
648*4882a593Smuzhiyun
649*4882a593Smuzhiyun	spin_lock_irqsave(&musb->lock, flags);
650*4882a593Smuzhiyun
651*4882a593Smuzhiyun	musb->int_usb = musb_readb(musb->mregs, MUSB_INTRUSB);
652*4882a593Smuzhiyun	musb->int_tx = musb_readw(musb->mregs, MUSB_INTRTX);
653*4882a593Smuzhiyun	musb->int_rx = musb_readw(musb->mregs, MUSB_INTRRX);
654*4882a593Smuzhiyun
655*4882a593Smuzhiyun	/*
656*4882a593Smuzhiyun	 * The controller is gadget only, the state of the host mode IRQ bits is
657*4882a593Smuzhiyun	 * undefined. Mask them to make sure that the musb driver core will
658*4882a593Smuzhiyun	 * never see them set
659*4882a593Smuzhiyun	 */
660*4882a593Smuzhiyun	musb->int_usb &= MUSB_INTR_SUSPEND | MUSB_INTR_RESUME |
661*4882a593Smuzhiyun	    MUSB_INTR_RESET | MUSB_INTR_SOF;
662*4882a593Smuzhiyun
663*4882a593Smuzhiyun	if (musb->int_usb || musb->int_tx || musb->int_rx)
664*4882a593Smuzhiyun	    retval = musb_interrupt(musb);
665*4882a593Smuzhiyun
666*4882a593Smuzhiyun	spin_unlock_irqrestore(&musb->lock, flags);
667*4882a593Smuzhiyun
668*4882a593Smuzhiyun	return retval;
669*4882a593Smuzhiyun    }
670*4882a593Smuzhiyun
671*4882a593SmuzhiyunInstruction on line 18 above is a way for the controller driver to work
672*4882a593Smuzhiyunaround the fact that some interrupt bits used for USB host mode
673*4882a593Smuzhiyunoperation are missing in the ``MUSB_INTRUSB`` register, thus left in an
674*4882a593Smuzhiyunundefined hardware state, since this MUSB controller hardware is used in
675*4882a593Smuzhiyunperipheral mode only. As a consequence, the glue layer masks these
676*4882a593Smuzhiyunmissing bits out to avoid parasite interrupts by doing a logical AND
677*4882a593Smuzhiyunoperation between the value read from ``MUSB_INTRUSB`` and the bits that
678*4882a593Smuzhiyunare actually implemented in the register.
679*4882a593Smuzhiyun
680*4882a593SmuzhiyunThese are only a couple of the quirks found in the JZ4740 USB device
681*4882a593Smuzhiyuncontroller. Some others were directly addressed in the MUSB core since
682*4882a593Smuzhiyunthe fixes were generic enough to provide a better handling of the issues
683*4882a593Smuzhiyunfor others controller hardware eventually.
684*4882a593Smuzhiyun
685*4882a593SmuzhiyunConclusion
686*4882a593Smuzhiyun==========
687*4882a593Smuzhiyun
688*4882a593SmuzhiyunWriting a Linux MUSB glue layer should be a more accessible task, as
689*4882a593Smuzhiyunthis documentation tries to show the ins and outs of this exercise.
690*4882a593Smuzhiyun
691*4882a593SmuzhiyunThe JZ4740 USB device controller being fairly simple, I hope its glue
692*4882a593Smuzhiyunlayer serves as a good example for the curious mind. Used with the
693*4882a593Smuzhiyuncurrent MUSB glue layers, this documentation should provide enough
694*4882a593Smuzhiyunguidance to get started; should anything gets out of hand, the linux-usb
695*4882a593Smuzhiyunmailing list archive is another helpful resource to browse through.
696*4882a593Smuzhiyun
697*4882a593SmuzhiyunAcknowledgements
698*4882a593Smuzhiyun================
699*4882a593Smuzhiyun
700*4882a593SmuzhiyunMany thanks to Lars-Peter Clausen and Maarten ter Huurne for answering
701*4882a593Smuzhiyunmy questions while I was writing the JZ4740 glue layer and for helping
702*4882a593Smuzhiyunme out getting the code in good shape.
703*4882a593Smuzhiyun
704*4882a593SmuzhiyunI would also like to thank the Qi-Hardware community at large for its
705*4882a593Smuzhiyuncheerful guidance and support.
706*4882a593Smuzhiyun
707*4882a593SmuzhiyunResources
708*4882a593Smuzhiyun=========
709*4882a593Smuzhiyun
710*4882a593SmuzhiyunUSB Home Page: https://www.usb.org
711*4882a593Smuzhiyun
712*4882a593Smuzhiyunlinux-usb Mailing List Archives: https://marc.info/?l=linux-usb
713*4882a593Smuzhiyun
714*4882a593SmuzhiyunUSB On-the-Go Basics:
715*4882a593Smuzhiyunhttps://www.maximintegrated.com/app-notes/index.mvp/id/1822
716*4882a593Smuzhiyun
717*4882a593Smuzhiyun:ref:`Writing USB Device Drivers <writing-usb-driver>`
718*4882a593Smuzhiyun
719*4882a593SmuzhiyunTexas Instruments USB Configuration Wiki Page:
720*4882a593Smuzhiyunhttp://processors.wiki.ti.com/index.php/Usbgeneralpage
721