167cc20e0SMauro Carvalho Chehab=========================
267cc20e0SMauro Carvalho ChehabWriting a MUSB Glue Layer
367cc20e0SMauro Carvalho Chehab=========================
44ad4b21bSMauro Carvalho Chehab
54ad4b21bSMauro Carvalho Chehab:Author: Apelete Seketeli
64ad4b21bSMauro Carvalho Chehab
74ad4b21bSMauro Carvalho ChehabIntroduction
84ad4b21bSMauro Carvalho Chehab============
94ad4b21bSMauro Carvalho Chehab
104ad4b21bSMauro Carvalho ChehabThe Linux MUSB subsystem is part of the larger Linux USB subsystem. It
114ad4b21bSMauro Carvalho Chehabprovides support for embedded USB Device Controllers (UDC) that do not
124ad4b21bSMauro Carvalho Chehabuse Universal Host Controller Interface (UHCI) or Open Host Controller
134ad4b21bSMauro Carvalho ChehabInterface (OHCI).
144ad4b21bSMauro Carvalho Chehab
154ad4b21bSMauro Carvalho ChehabInstead, these embedded UDC rely on the USB On-the-Go (OTG)
164ad4b21bSMauro Carvalho Chehabspecification which they implement at least partially. The silicon
174ad4b21bSMauro Carvalho Chehabreference design used in most cases is the Multipoint USB Highspeed
184ad4b21bSMauro Carvalho ChehabDual-Role Controller (MUSB HDRC) found in the Mentor Graphics Inventra™
194ad4b21bSMauro Carvalho Chehabdesign.
204ad4b21bSMauro Carvalho Chehab
214ad4b21bSMauro Carvalho ChehabAs a self-taught exercise I have written an MUSB glue layer for the
224ad4b21bSMauro Carvalho ChehabIngenic JZ4740 SoC, modelled after the many MUSB glue layers in the
234ad4b21bSMauro Carvalho Chehabkernel source tree. This layer can be found at
2467cc20e0SMauro Carvalho Chehab``drivers/usb/musb/jz4740.c``. In this documentation I will walk through the
2567cc20e0SMauro Carvalho Chehabbasics of the ``jz4740.c`` glue layer, explaining the different pieces and
264ad4b21bSMauro Carvalho Chehabwhat needs to be done in order to write your own device glue layer.
274ad4b21bSMauro Carvalho Chehab
2867cc20e0SMauro Carvalho Chehab.. _musb-basics:
2967cc20e0SMauro Carvalho Chehab
304ad4b21bSMauro Carvalho ChehabLinux MUSB Basics
314ad4b21bSMauro Carvalho Chehab=================
324ad4b21bSMauro Carvalho Chehab
334ad4b21bSMauro Carvalho ChehabTo get started on the topic, please read USB On-the-Go Basics (see
344ad4b21bSMauro Carvalho ChehabResources) which provides an introduction of USB OTG operation at the
354ad4b21bSMauro Carvalho Chehabhardware level. A couple of wiki pages by Texas Instruments and Analog
364ad4b21bSMauro Carvalho ChehabDevices also provide an overview of the Linux kernel MUSB configuration,
374ad4b21bSMauro Carvalho Chehabalbeit focused on some specific devices provided by these companies.
384ad4b21bSMauro Carvalho ChehabFinally, getting acquainted with the USB specification at USB home page
394ad4b21bSMauro Carvalho Chehabmay come in handy, with practical instance provided through the Writing
404ad4b21bSMauro Carvalho ChehabUSB Device Drivers documentation (again, see Resources).
414ad4b21bSMauro Carvalho Chehab
424ad4b21bSMauro Carvalho ChehabLinux USB stack is a layered architecture in which the MUSB controller
434ad4b21bSMauro Carvalho Chehabhardware sits at the lowest. The MUSB controller driver abstract the
4467cc20e0SMauro Carvalho ChehabMUSB controller hardware to the Linux USB stack::
454ad4b21bSMauro Carvalho Chehab
464ad4b21bSMauro Carvalho Chehab	  ------------------------
474ad4b21bSMauro Carvalho Chehab	  |                      | <------- drivers/usb/gadget
484ad4b21bSMauro Carvalho Chehab	  | Linux USB Core Stack | <------- drivers/usb/host
494ad4b21bSMauro Carvalho Chehab	  |                      | <------- drivers/usb/core
504ad4b21bSMauro Carvalho Chehab	  ------------------------
514ad4b21bSMauro Carvalho Chehab524ad4b21bSMauro Carvalho Chehab	 --------------------------
534ad4b21bSMauro Carvalho Chehab	 |                        | <------ drivers/usb/musb/musb_gadget.c
544ad4b21bSMauro Carvalho Chehab	 | MUSB Controller driver | <------ drivers/usb/musb/musb_host.c
554ad4b21bSMauro Carvalho Chehab	 |                        | <------ drivers/usb/musb/musb_core.c
564ad4b21bSMauro Carvalho Chehab	 --------------------------
574ad4b21bSMauro Carvalho Chehab584ad4b21bSMauro Carvalho Chehab      ---------------------------------
594ad4b21bSMauro Carvalho Chehab      | MUSB Platform Specific Driver |
604ad4b21bSMauro Carvalho Chehab      |                               | <-- drivers/usb/musb/jz4740.c
614ad4b21bSMauro Carvalho Chehab      |       aka "Glue Layer"        |
624ad4b21bSMauro Carvalho Chehab      ---------------------------------
634ad4b21bSMauro Carvalho Chehab644ad4b21bSMauro Carvalho Chehab      ---------------------------------
654ad4b21bSMauro Carvalho Chehab      |   MUSB Controller Hardware    |
664ad4b21bSMauro Carvalho Chehab      ---------------------------------
674ad4b21bSMauro Carvalho Chehab
684ad4b21bSMauro Carvalho ChehabAs outlined above, the glue layer is actually the platform specific code
694ad4b21bSMauro Carvalho Chehabsitting in between the controller driver and the controller hardware.
704ad4b21bSMauro Carvalho Chehab
714ad4b21bSMauro Carvalho ChehabJust like a Linux USB driver needs to register itself with the Linux USB
724ad4b21bSMauro Carvalho Chehabsubsystem, the MUSB glue layer needs first to register itself with the
734ad4b21bSMauro Carvalho ChehabMUSB controller driver. This will allow the controller driver to know
744ad4b21bSMauro Carvalho Chehababout which device the glue layer supports and which functions to call
754ad4b21bSMauro Carvalho Chehabwhen a supported device is detected or released; remember we are talking
764ad4b21bSMauro Carvalho Chehababout an embedded controller chip here, so no insertion or removal at
774ad4b21bSMauro Carvalho Chehabrun-time.
784ad4b21bSMauro Carvalho Chehab
794ad4b21bSMauro Carvalho ChehabAll of this information is passed to the MUSB controller driver through
8067cc20e0SMauro Carvalho Chehaba :c:type:`platform_driver` structure defined in the glue layer as::
814ad4b21bSMauro Carvalho Chehab
824ad4b21bSMauro Carvalho Chehab    static struct platform_driver jz4740_driver = {
834ad4b21bSMauro Carvalho Chehab	.probe      = jz4740_probe,
844ad4b21bSMauro Carvalho Chehab	.remove     = jz4740_remove,
854ad4b21bSMauro Carvalho Chehab	.driver     = {
864ad4b21bSMauro Carvalho Chehab	    .name   = "musb-jz4740",
874ad4b21bSMauro Carvalho Chehab	},
884ad4b21bSMauro Carvalho Chehab    };
894ad4b21bSMauro Carvalho Chehab
904ad4b21bSMauro Carvalho ChehabThe probe and remove function pointers are called when a matching device
914ad4b21bSMauro Carvalho Chehabis detected and, respectively, released. The name string describes the
924ad4b21bSMauro Carvalho Chehabdevice supported by this glue layer. In the current case it matches a
9367cc20e0SMauro Carvalho Chehabplatform_device structure declared in ``arch/mips/jz4740/platform.c``. Note
944ad4b21bSMauro Carvalho Chehabthat we are not using device tree bindings here.
954ad4b21bSMauro Carvalho Chehab
964ad4b21bSMauro Carvalho ChehabIn order to register itself to the controller driver, the glue layer
974ad4b21bSMauro Carvalho Chehabgoes through a few steps, basically allocating the controller hardware
984ad4b21bSMauro Carvalho Chehabresources and initialising a couple of circuits. To do so, it needs to
994ad4b21bSMauro Carvalho Chehabkeep track of the information used throughout these steps. This is done
10067cc20e0SMauro Carvalho Chehabby defining a private ``jz4740_glue`` structure::
1014ad4b21bSMauro Carvalho Chehab
1024ad4b21bSMauro Carvalho Chehab    struct jz4740_glue {
1034ad4b21bSMauro Carvalho Chehab	struct device           *dev;
1044ad4b21bSMauro Carvalho Chehab	struct platform_device  *musb;
1054ad4b21bSMauro Carvalho Chehab	struct clk      *clk;
1064ad4b21bSMauro Carvalho Chehab    };
1074ad4b21bSMauro Carvalho Chehab
1084ad4b21bSMauro Carvalho Chehab
1094ad4b21bSMauro Carvalho ChehabThe dev and musb members are both device structure variables. The first
1104ad4b21bSMauro Carvalho Chehabone holds generic information about the device, since it's the basic
1114ad4b21bSMauro Carvalho Chehabdevice structure, and the latter holds information more closely related
1124ad4b21bSMauro Carvalho Chehabto the subsystem the device is registered to. The clk variable keeps
1134ad4b21bSMauro Carvalho Chehabinformation related to the device clock operation.
1144ad4b21bSMauro Carvalho Chehab
1154ad4b21bSMauro Carvalho ChehabLet's go through the steps of the probe function that leads the glue
1164ad4b21bSMauro Carvalho Chehablayer to register itself to the controller driver.
1174ad4b21bSMauro Carvalho Chehab
11867cc20e0SMauro Carvalho Chehab.. note::
11967cc20e0SMauro Carvalho Chehab
12067cc20e0SMauro Carvalho Chehab   For the sake of readability each function will be split in logical
1214ad4b21bSMauro Carvalho Chehab   parts, each part being shown as if it was independent from the others.
1224ad4b21bSMauro Carvalho Chehab
12367cc20e0SMauro Carvalho Chehab.. code-block:: c
12467cc20e0SMauro Carvalho Chehab    :emphasize-lines: 8,12,18
1254ad4b21bSMauro Carvalho Chehab
1264ad4b21bSMauro Carvalho Chehab    static int jz4740_probe(struct platform_device *pdev)
1274ad4b21bSMauro Carvalho Chehab    {
1284ad4b21bSMauro Carvalho Chehab	struct platform_device      *musb;
1294ad4b21bSMauro Carvalho Chehab	struct jz4740_glue      *glue;
1304ad4b21bSMauro Carvalho Chehab	struct clk                      *clk;
1314ad4b21bSMauro Carvalho Chehab	int             ret;
1324ad4b21bSMauro Carvalho Chehab
1334ad4b21bSMauro Carvalho Chehab	glue = devm_kzalloc(&pdev->dev, sizeof(*glue), GFP_KERNEL);
1344ad4b21bSMauro Carvalho Chehab	if (!glue)
1354ad4b21bSMauro Carvalho Chehab	    return -ENOMEM;
1364ad4b21bSMauro Carvalho Chehab
1374ad4b21bSMauro Carvalho Chehab	musb = platform_device_alloc("musb-hdrc", PLATFORM_DEVID_AUTO);
1384ad4b21bSMauro Carvalho Chehab	if (!musb) {
1394ad4b21bSMauro Carvalho Chehab	    dev_err(&pdev->dev, "failed to allocate musb device\n");
1404ad4b21bSMauro Carvalho Chehab	    return -ENOMEM;
1414ad4b21bSMauro Carvalho Chehab	}
1424ad4b21bSMauro Carvalho Chehab
1434ad4b21bSMauro Carvalho Chehab	clk = devm_clk_get(&pdev->dev, "udc");
1444ad4b21bSMauro Carvalho Chehab	if (IS_ERR(clk)) {
1454ad4b21bSMauro Carvalho Chehab	    dev_err(&pdev->dev, "failed to get clock\n");
1464ad4b21bSMauro Carvalho Chehab	    ret = PTR_ERR(clk);
1474ad4b21bSMauro Carvalho Chehab	    goto err_platform_device_put;
1484ad4b21bSMauro Carvalho Chehab	}
1494ad4b21bSMauro Carvalho Chehab
1504ad4b21bSMauro Carvalho Chehab	ret = clk_prepare_enable(clk);
1514ad4b21bSMauro Carvalho Chehab	if (ret) {
1524ad4b21bSMauro Carvalho Chehab	    dev_err(&pdev->dev, "failed to enable clock\n");
1534ad4b21bSMauro Carvalho Chehab	    goto err_platform_device_put;
1544ad4b21bSMauro Carvalho Chehab	}
1554ad4b21bSMauro Carvalho Chehab
1564ad4b21bSMauro Carvalho Chehab	musb->dev.parent        = &pdev->dev;
1574ad4b21bSMauro Carvalho Chehab
1584ad4b21bSMauro Carvalho Chehab	glue->dev           = &pdev->dev;
1594ad4b21bSMauro Carvalho Chehab	glue->musb          = musb;
1604ad4b21bSMauro Carvalho Chehab	glue->clk           = clk;
1614ad4b21bSMauro Carvalho Chehab
1624ad4b21bSMauro Carvalho Chehab	return 0;
1634ad4b21bSMauro Carvalho Chehab
1644ad4b21bSMauro Carvalho Chehab    err_platform_device_put:
1654ad4b21bSMauro Carvalho Chehab	platform_device_put(musb);
1664ad4b21bSMauro Carvalho Chehab	return ret;
1674ad4b21bSMauro Carvalho Chehab    }
1684ad4b21bSMauro Carvalho Chehab
1694ad4b21bSMauro Carvalho ChehabThe first few lines of the probe function allocate and assign the glue,
17067cc20e0SMauro Carvalho Chehabmusb and clk variables. The ``GFP_KERNEL`` flag (line 8) allows the
1714ad4b21bSMauro Carvalho Chehaballocation process to sleep and wait for memory, thus being usable in a
17267cc20e0SMauro Carvalho Chehablocking situation. The ``PLATFORM_DEVID_AUTO`` flag (line 12) allows
1734ad4b21bSMauro Carvalho Chehabautomatic allocation and management of device IDs in order to avoid
17467cc20e0SMauro Carvalho Chehabdevice namespace collisions with explicit IDs. With :c:func:`devm_clk_get`
1754ad4b21bSMauro Carvalho Chehab(line 18) the glue layer allocates the clock -- the ``devm_`` prefix
17667cc20e0SMauro Carvalho Chehabindicates that :c:func:`clk_get` is managed: it automatically frees the
1774ad4b21bSMauro Carvalho Chehaballocated clock resource data when the device is released -- and enable
1784ad4b21bSMauro Carvalho Chehabit.
1794ad4b21bSMauro Carvalho Chehab
18067cc20e0SMauro Carvalho Chehab
18167cc20e0SMauro Carvalho Chehab
1824ad4b21bSMauro Carvalho ChehabThen comes the registration steps:
1834ad4b21bSMauro Carvalho Chehab
18467cc20e0SMauro Carvalho Chehab.. code-block:: c
18567cc20e0SMauro Carvalho Chehab    :emphasize-lines: 3,5,7,9,16
1864ad4b21bSMauro Carvalho Chehab
1874ad4b21bSMauro Carvalho Chehab    static int jz4740_probe(struct platform_device *pdev)
1884ad4b21bSMauro Carvalho Chehab    {
1894ad4b21bSMauro Carvalho Chehab	struct musb_hdrc_platform_data  *pdata = &jz4740_musb_platform_data;
1904ad4b21bSMauro Carvalho Chehab
1914ad4b21bSMauro Carvalho Chehab	pdata->platform_ops     = &jz4740_musb_ops;
1924ad4b21bSMauro Carvalho Chehab
1934ad4b21bSMauro Carvalho Chehab	platform_set_drvdata(pdev, glue);
1944ad4b21bSMauro Carvalho Chehab
1954ad4b21bSMauro Carvalho Chehab	ret = platform_device_add_resources(musb, pdev->resource,
1964ad4b21bSMauro Carvalho Chehab			    pdev->num_resources);
1974ad4b21bSMauro Carvalho Chehab	if (ret) {
1984ad4b21bSMauro Carvalho Chehab	    dev_err(&pdev->dev, "failed to add resources\n");
1994ad4b21bSMauro Carvalho Chehab	    goto err_clk_disable;
2004ad4b21bSMauro Carvalho Chehab	}
2014ad4b21bSMauro Carvalho Chehab
2024ad4b21bSMauro Carvalho Chehab	ret = platform_device_add_data(musb, pdata, sizeof(*pdata));
2034ad4b21bSMauro Carvalho Chehab	if (ret) {
2044ad4b21bSMauro Carvalho Chehab	    dev_err(&pdev->dev, "failed to add platform_data\n");
2054ad4b21bSMauro Carvalho Chehab	    goto err_clk_disable;
2064ad4b21bSMauro Carvalho Chehab	}
2074ad4b21bSMauro Carvalho Chehab
2084ad4b21bSMauro Carvalho Chehab	return 0;
2094ad4b21bSMauro Carvalho Chehab
2104ad4b21bSMauro Carvalho Chehab    err_clk_disable:
2114ad4b21bSMauro Carvalho Chehab	clk_disable_unprepare(clk);
2124ad4b21bSMauro Carvalho Chehab    err_platform_device_put:
2134ad4b21bSMauro Carvalho Chehab	platform_device_put(musb);
2144ad4b21bSMauro Carvalho Chehab	return ret;
2154ad4b21bSMauro Carvalho Chehab    }
2164ad4b21bSMauro Carvalho Chehab
2174ad4b21bSMauro Carvalho ChehabThe first step is to pass the device data privately held by the glue
21867cc20e0SMauro Carvalho Chehablayer on to the controller driver through :c:func:`platform_set_drvdata`
21967cc20e0SMauro Carvalho Chehab(line 7). Next is passing on the device resources information, also privately
22067cc20e0SMauro Carvalho Chehabheld at that point, through :c:func:`platform_device_add_resources` (line 9).
2214ad4b21bSMauro Carvalho Chehab
2224ad4b21bSMauro Carvalho ChehabFinally comes passing on the platform specific data to the controller
22367cc20e0SMauro Carvalho Chehabdriver (line 16). Platform data will be discussed in
22467cc20e0SMauro Carvalho Chehab:ref:`musb-dev-platform-data`, but here we are looking at the
22567cc20e0SMauro Carvalho Chehab``platform_ops`` function pointer (line 5) in ``musb_hdrc_platform_data``
2264ad4b21bSMauro Carvalho Chehabstructure (line 3). This function pointer allows the MUSB controller
22767cc20e0SMauro Carvalho Chehabdriver to know which function to call for device operation::
2284ad4b21bSMauro Carvalho Chehab
2294ad4b21bSMauro Carvalho Chehab    static const struct musb_platform_ops jz4740_musb_ops = {
2304ad4b21bSMauro Carvalho Chehab	.init       = jz4740_musb_init,
2314ad4b21bSMauro Carvalho Chehab	.exit       = jz4740_musb_exit,
2324ad4b21bSMauro Carvalho Chehab    };
2334ad4b21bSMauro Carvalho Chehab
2344ad4b21bSMauro Carvalho ChehabHere we have the minimal case where only init and exit functions are
2354ad4b21bSMauro Carvalho Chehabcalled by the controller driver when needed. Fact is the JZ4740 MUSB
2364ad4b21bSMauro Carvalho Chehabcontroller is a basic controller, lacking some features found in other
2374ad4b21bSMauro Carvalho Chehabcontrollers, otherwise we may also have pointers to a few other
2384ad4b21bSMauro Carvalho Chehabfunctions like a power management function or a function to switch
2394ad4b21bSMauro Carvalho Chehabbetween OTG and non-OTG modes, for instance.
2404ad4b21bSMauro Carvalho Chehab
2414ad4b21bSMauro Carvalho ChehabAt that point of the registration process, the controller driver
2424ad4b21bSMauro Carvalho Chehabactually calls the init function:
2434ad4b21bSMauro Carvalho Chehab
24467cc20e0SMauro Carvalho Chehab   .. code-block:: c
24567cc20e0SMauro Carvalho Chehab    :emphasize-lines: 12,14
2464ad4b21bSMauro Carvalho Chehab
2474ad4b21bSMauro Carvalho Chehab    static int jz4740_musb_init(struct musb *musb)
2484ad4b21bSMauro Carvalho Chehab    {
2494ad4b21bSMauro Carvalho Chehab	musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2);
2504ad4b21bSMauro Carvalho Chehab	if (!musb->xceiv) {
2514ad4b21bSMauro Carvalho Chehab	    pr_err("HS UDC: no transceiver configured\n");
2524ad4b21bSMauro Carvalho Chehab	    return -ENODEV;
2534ad4b21bSMauro Carvalho Chehab	}
2544ad4b21bSMauro Carvalho Chehab
2554ad4b21bSMauro Carvalho Chehab	/* Silicon does not implement ConfigData register.
2564ad4b21bSMauro Carvalho Chehab	 * Set dyn_fifo to avoid reading EP config from hardware.
2574ad4b21bSMauro Carvalho Chehab	 */
2584ad4b21bSMauro Carvalho Chehab	musb->dyn_fifo = true;
2594ad4b21bSMauro Carvalho Chehab
2604ad4b21bSMauro Carvalho Chehab	musb->isr = jz4740_musb_interrupt;
2614ad4b21bSMauro Carvalho Chehab
2624ad4b21bSMauro Carvalho Chehab	return 0;
2634ad4b21bSMauro Carvalho Chehab    }
2644ad4b21bSMauro Carvalho Chehab
26567cc20e0SMauro Carvalho ChehabThe goal of ``jz4740_musb_init()`` is to get hold of the transceiver
2664ad4b21bSMauro Carvalho Chehabdriver data of the MUSB controller hardware and pass it on to the MUSB
2674ad4b21bSMauro Carvalho Chehabcontroller driver, as usual. The transceiver is the circuitry inside the
2684ad4b21bSMauro Carvalho Chehabcontroller hardware responsible for sending/receiving the USB data.
2694ad4b21bSMauro Carvalho ChehabSince it is an implementation of the physical layer of the OSI model,
2704ad4b21bSMauro Carvalho Chehabthe transceiver is also referred to as PHY.
2714ad4b21bSMauro Carvalho Chehab
27267cc20e0SMauro Carvalho ChehabGetting hold of the ``MUSB PHY`` driver data is done with ``usb_get_phy()``
2734ad4b21bSMauro Carvalho Chehabwhich returns a pointer to the structure containing the driver instance
2744ad4b21bSMauro Carvalho Chehabdata. The next couple of instructions (line 12 and 14) are used as a
2754ad4b21bSMauro Carvalho Chehabquirk and to setup IRQ handling respectively. Quirks and IRQ handling
27667cc20e0SMauro Carvalho Chehabwill be discussed later in :ref:`musb-dev-quirks` and
27767cc20e0SMauro Carvalho Chehab:ref:`musb-handling-irqs`\ ::
2784ad4b21bSMauro Carvalho Chehab
2794ad4b21bSMauro Carvalho Chehab    static int jz4740_musb_exit(struct musb *musb)
2804ad4b21bSMauro Carvalho Chehab    {
2814ad4b21bSMauro Carvalho Chehab	usb_put_phy(musb->xceiv);
2824ad4b21bSMauro Carvalho Chehab
2834ad4b21bSMauro Carvalho Chehab	return 0;
2844ad4b21bSMauro Carvalho Chehab    }
2854ad4b21bSMauro Carvalho Chehab
2864ad4b21bSMauro Carvalho ChehabActing as the counterpart of init, the exit function releases the MUSB
2874ad4b21bSMauro Carvalho ChehabPHY driver when the controller hardware itself is about to be released.
2884ad4b21bSMauro Carvalho Chehab
2894ad4b21bSMauro Carvalho ChehabAgain, note that init and exit are fairly simple in this case due to the
2904ad4b21bSMauro Carvalho Chehabbasic set of features of the JZ4740 controller hardware. When writing an
2914ad4b21bSMauro Carvalho Chehabmusb glue layer for a more complex controller hardware, you might need
2924ad4b21bSMauro Carvalho Chehabto take care of more processing in those two functions.
2934ad4b21bSMauro Carvalho Chehab
2944ad4b21bSMauro Carvalho ChehabReturning from the init function, the MUSB controller driver jumps back
29567cc20e0SMauro Carvalho Chehabinto the probe function::
2964ad4b21bSMauro Carvalho Chehab
2974ad4b21bSMauro Carvalho Chehab    static int jz4740_probe(struct platform_device *pdev)
2984ad4b21bSMauro Carvalho Chehab    {
2994ad4b21bSMauro Carvalho Chehab	ret = platform_device_add(musb);
3004ad4b21bSMauro Carvalho Chehab	if (ret) {
3014ad4b21bSMauro Carvalho Chehab	    dev_err(&pdev->dev, "failed to register musb device\n");
3024ad4b21bSMauro Carvalho Chehab	    goto err_clk_disable;
3034ad4b21bSMauro Carvalho Chehab	}
3044ad4b21bSMauro Carvalho Chehab
3054ad4b21bSMauro Carvalho Chehab	return 0;
3064ad4b21bSMauro Carvalho Chehab
3074ad4b21bSMauro Carvalho Chehab    err_clk_disable:
3084ad4b21bSMauro Carvalho Chehab	clk_disable_unprepare(clk);
3094ad4b21bSMauro Carvalho Chehab    err_platform_device_put:
3104ad4b21bSMauro Carvalho Chehab	platform_device_put(musb);
3114ad4b21bSMauro Carvalho Chehab	return ret;
3124ad4b21bSMauro Carvalho Chehab    }
3134ad4b21bSMauro Carvalho Chehab
3144ad4b21bSMauro Carvalho ChehabThis is the last part of the device registration process where the glue
3154ad4b21bSMauro Carvalho Chehablayer adds the controller hardware device to Linux kernel device
3164ad4b21bSMauro Carvalho Chehabhierarchy: at this stage, all known information about the device is
31767cc20e0SMauro Carvalho Chehabpassed on to the Linux USB core stack:
3184ad4b21bSMauro Carvalho Chehab
31967cc20e0SMauro Carvalho Chehab   .. code-block:: c
32067cc20e0SMauro Carvalho Chehab    :emphasize-lines: 5,6
3214ad4b21bSMauro Carvalho Chehab
3224ad4b21bSMauro Carvalho Chehab    static int jz4740_remove(struct platform_device *pdev)
3234ad4b21bSMauro Carvalho Chehab    {
3244ad4b21bSMauro Carvalho Chehab	struct jz4740_glue  *glue = platform_get_drvdata(pdev);
3254ad4b21bSMauro Carvalho Chehab
3264ad4b21bSMauro Carvalho Chehab	platform_device_unregister(glue->musb);
3274ad4b21bSMauro Carvalho Chehab	clk_disable_unprepare(glue->clk);
3284ad4b21bSMauro Carvalho Chehab
3294ad4b21bSMauro Carvalho Chehab	return 0;
3304ad4b21bSMauro Carvalho Chehab    }
3314ad4b21bSMauro Carvalho Chehab
3324ad4b21bSMauro Carvalho ChehabActing as the counterpart of probe, the remove function unregister the
3334ad4b21bSMauro Carvalho ChehabMUSB controller hardware (line 5) and disable the clock (line 6),
3344ad4b21bSMauro Carvalho Chehaballowing it to be gated.
3354ad4b21bSMauro Carvalho Chehab
33667cc20e0SMauro Carvalho Chehab.. _musb-handling-irqs:
33767cc20e0SMauro Carvalho Chehab
3384ad4b21bSMauro Carvalho ChehabHandling IRQs
3394ad4b21bSMauro Carvalho Chehab=============
3404ad4b21bSMauro Carvalho Chehab
3414ad4b21bSMauro Carvalho ChehabAdditionally to the MUSB controller hardware basic setup and
3424ad4b21bSMauro Carvalho Chehabregistration, the glue layer is also responsible for handling the IRQs:
3434ad4b21bSMauro Carvalho Chehab
34467cc20e0SMauro Carvalho Chehab   .. code-block:: c
34567cc20e0SMauro Carvalho Chehab    :emphasize-lines: 7,9-11,14,24
3464ad4b21bSMauro Carvalho Chehab
3474ad4b21bSMauro Carvalho Chehab    static irqreturn_t jz4740_musb_interrupt(int irq, void *__hci)
3484ad4b21bSMauro Carvalho Chehab    {
3494ad4b21bSMauro Carvalho Chehab	unsigned long   flags;
3504ad4b21bSMauro Carvalho Chehab	irqreturn_t     retval = IRQ_NONE;
3514ad4b21bSMauro Carvalho Chehab	struct musb     *musb = __hci;
3524ad4b21bSMauro Carvalho Chehab
3534ad4b21bSMauro Carvalho Chehab	spin_lock_irqsave(&musb->lock, flags);
3544ad4b21bSMauro Carvalho Chehab
3554ad4b21bSMauro Carvalho Chehab	musb->int_usb = musb_readb(musb->mregs, MUSB_INTRUSB);
3564ad4b21bSMauro Carvalho Chehab	musb->int_tx = musb_readw(musb->mregs, MUSB_INTRTX);
3574ad4b21bSMauro Carvalho Chehab	musb->int_rx = musb_readw(musb->mregs, MUSB_INTRRX);
3584ad4b21bSMauro Carvalho Chehab
3594ad4b21bSMauro Carvalho Chehab	/*
3604ad4b21bSMauro Carvalho Chehab	 * The controller is gadget only, the state of the host mode IRQ bits is
3614ad4b21bSMauro Carvalho Chehab	 * undefined. Mask them to make sure that the musb driver core will
3624ad4b21bSMauro Carvalho Chehab	 * never see them set
3634ad4b21bSMauro Carvalho Chehab	 */
3644ad4b21bSMauro Carvalho Chehab	musb->int_usb &= MUSB_INTR_SUSPEND | MUSB_INTR_RESUME |
3654ad4b21bSMauro Carvalho Chehab	    MUSB_INTR_RESET | MUSB_INTR_SOF;
3664ad4b21bSMauro Carvalho Chehab
3674ad4b21bSMauro Carvalho Chehab	if (musb->int_usb || musb->int_tx || musb->int_rx)
3684ad4b21bSMauro Carvalho Chehab	    retval = musb_interrupt(musb);
3694ad4b21bSMauro Carvalho Chehab
3704ad4b21bSMauro Carvalho Chehab	spin_unlock_irqrestore(&musb->lock, flags);
3714ad4b21bSMauro Carvalho Chehab
3724ad4b21bSMauro Carvalho Chehab	return retval;
3734ad4b21bSMauro Carvalho Chehab    }
3744ad4b21bSMauro Carvalho Chehab
3754ad4b21bSMauro Carvalho ChehabHere the glue layer mostly has to read the relevant hardware registers
3764ad4b21bSMauro Carvalho Chehaband pass their values on to the controller driver which will handle the
3774ad4b21bSMauro Carvalho Chehabactual event that triggered the IRQ.
3784ad4b21bSMauro Carvalho Chehab
3794ad4b21bSMauro Carvalho ChehabThe interrupt handler critical section is protected by the
38067cc20e0SMauro Carvalho Chehab:c:func:`spin_lock_irqsave` and counterpart :c:func:`spin_unlock_irqrestore`
3814ad4b21bSMauro Carvalho Chehabfunctions (line 7 and 24 respectively), which prevent the interrupt
3824ad4b21bSMauro Carvalho Chehabhandler code to be run by two different threads at the same time.
3834ad4b21bSMauro Carvalho Chehab
3844ad4b21bSMauro Carvalho ChehabThen the relevant interrupt registers are read (line 9 to 11):
3854ad4b21bSMauro Carvalho Chehab
38667cc20e0SMauro Carvalho Chehab-  ``MUSB_INTRUSB``: indicates which USB interrupts are currently active,
3874ad4b21bSMauro Carvalho Chehab
38867cc20e0SMauro Carvalho Chehab-  ``MUSB_INTRTX``: indicates which of the interrupts for TX endpoints are
3894ad4b21bSMauro Carvalho Chehab   currently active,
3904ad4b21bSMauro Carvalho Chehab
39167cc20e0SMauro Carvalho Chehab-  ``MUSB_INTRRX``: indicates which of the interrupts for TX endpoints are
3924ad4b21bSMauro Carvalho Chehab   currently active.
3934ad4b21bSMauro Carvalho Chehab
39467cc20e0SMauro Carvalho ChehabNote that :c:func:`musb_readb` is used to read 8-bit registers at most, while
39567cc20e0SMauro Carvalho Chehab:c:func:`musb_readw` allows us to read at most 16-bit registers. There are
3964ad4b21bSMauro Carvalho Chehabother functions that can be used depending on the size of your device
39767cc20e0SMauro Carvalho Chehabregisters. See ``musb_io.h`` for more information.
3984ad4b21bSMauro Carvalho Chehab
3994ad4b21bSMauro Carvalho ChehabInstruction on line 18 is another quirk specific to the JZ4740 USB
40067cc20e0SMauro Carvalho Chehabdevice controller, which will be discussed later in :ref:`musb-dev-quirks`.
4014ad4b21bSMauro Carvalho Chehab
4024ad4b21bSMauro Carvalho ChehabThe glue layer still needs to register the IRQ handler though. Remember
40367cc20e0SMauro Carvalho Chehabthe instruction on line 14 of the init function::
4044ad4b21bSMauro Carvalho Chehab
4054ad4b21bSMauro Carvalho Chehab    static int jz4740_musb_init(struct musb *musb)
4064ad4b21bSMauro Carvalho Chehab    {
4074ad4b21bSMauro Carvalho Chehab	musb->isr = jz4740_musb_interrupt;
4084ad4b21bSMauro Carvalho Chehab
4094ad4b21bSMauro Carvalho Chehab	return 0;
4104ad4b21bSMauro Carvalho Chehab    }
4114ad4b21bSMauro Carvalho Chehab
4124ad4b21bSMauro Carvalho ChehabThis instruction sets a pointer to the glue layer IRQ handler function,
4134ad4b21bSMauro Carvalho Chehabin order for the controller hardware to call the handler back when an
4144ad4b21bSMauro Carvalho ChehabIRQ comes from the controller hardware. The interrupt handler is now
4154ad4b21bSMauro Carvalho Chehabimplemented and registered.
4164ad4b21bSMauro Carvalho Chehab
41767cc20e0SMauro Carvalho Chehab.. _musb-dev-platform-data:
41867cc20e0SMauro Carvalho Chehab
4194ad4b21bSMauro Carvalho ChehabDevice Platform Data
4204ad4b21bSMauro Carvalho Chehab====================
4214ad4b21bSMauro Carvalho Chehab
4224ad4b21bSMauro Carvalho ChehabIn order to write an MUSB glue layer, you need to have some data
4234ad4b21bSMauro Carvalho Chehabdescribing the hardware capabilities of your controller hardware, which
4244ad4b21bSMauro Carvalho Chehabis called the platform data.
4254ad4b21bSMauro Carvalho Chehab
4264ad4b21bSMauro Carvalho ChehabPlatform data is specific to your hardware, though it may cover a broad
42767cc20e0SMauro Carvalho Chehabrange of devices, and is generally found somewhere in the ``arch/``
4284ad4b21bSMauro Carvalho Chehabdirectory, depending on your device architecture.
4294ad4b21bSMauro Carvalho Chehab
4304ad4b21bSMauro Carvalho ChehabFor instance, platform data for the JZ4740 SoC is found in
43167cc20e0SMauro Carvalho Chehab``arch/mips/jz4740/platform.c``. In the ``platform.c`` file each device of the
4324ad4b21bSMauro Carvalho ChehabJZ4740 SoC is described through a set of structures.
4334ad4b21bSMauro Carvalho Chehab
43467cc20e0SMauro Carvalho ChehabHere is the part of ``arch/mips/jz4740/platform.c`` that covers the USB
4354ad4b21bSMauro Carvalho ChehabDevice Controller (UDC):
4364ad4b21bSMauro Carvalho Chehab
43767cc20e0SMauro Carvalho Chehab   .. code-block:: c
43867cc20e0SMauro Carvalho Chehab    :emphasize-lines: 2,7,14-17,21,22,25,26,28,29
4394ad4b21bSMauro Carvalho Chehab
4404ad4b21bSMauro Carvalho Chehab    /* USB Device Controller */
4414ad4b21bSMauro Carvalho Chehab    struct platform_device jz4740_udc_xceiv_device = {
4424ad4b21bSMauro Carvalho Chehab	.name = "usb_phy_gen_xceiv",
4434ad4b21bSMauro Carvalho Chehab	.id   = 0,
4444ad4b21bSMauro Carvalho Chehab    };
4454ad4b21bSMauro Carvalho Chehab
4464ad4b21bSMauro Carvalho Chehab    static struct resource jz4740_udc_resources[] = {
4474ad4b21bSMauro Carvalho Chehab	[0] = {
4484ad4b21bSMauro Carvalho Chehab	    .start = JZ4740_UDC_BASE_ADDR,
4494ad4b21bSMauro Carvalho Chehab	    .end   = JZ4740_UDC_BASE_ADDR + 0x10000 - 1,
4504ad4b21bSMauro Carvalho Chehab	    .flags = IORESOURCE_MEM,
4514ad4b21bSMauro Carvalho Chehab	},
4524ad4b21bSMauro Carvalho Chehab	[1] = {
4534ad4b21bSMauro Carvalho Chehab	    .start = JZ4740_IRQ_UDC,
4544ad4b21bSMauro Carvalho Chehab	    .end   = JZ4740_IRQ_UDC,
4554ad4b21bSMauro Carvalho Chehab	    .flags = IORESOURCE_IRQ,
4564ad4b21bSMauro Carvalho Chehab	    .name  = "mc",
4574ad4b21bSMauro Carvalho Chehab	},
4584ad4b21bSMauro Carvalho Chehab    };
4594ad4b21bSMauro Carvalho Chehab
4604ad4b21bSMauro Carvalho Chehab    struct platform_device jz4740_udc_device = {
4614ad4b21bSMauro Carvalho Chehab	.name = "musb-jz4740",
4624ad4b21bSMauro Carvalho Chehab	.id   = -1,
4634ad4b21bSMauro Carvalho Chehab	.dev  = {
4644ad4b21bSMauro Carvalho Chehab	    .dma_mask          = &jz4740_udc_device.dev.coherent_dma_mask,
4654ad4b21bSMauro Carvalho Chehab	    .coherent_dma_mask = DMA_BIT_MASK(32),
4664ad4b21bSMauro Carvalho Chehab	},
4674ad4b21bSMauro Carvalho Chehab	.num_resources = ARRAY_SIZE(jz4740_udc_resources),
4684ad4b21bSMauro Carvalho Chehab	.resource      = jz4740_udc_resources,
4694ad4b21bSMauro Carvalho Chehab    };
4704ad4b21bSMauro Carvalho Chehab
47167cc20e0SMauro Carvalho ChehabThe ``jz4740_udc_xceiv_device`` platform device structure (line 2)
4724ad4b21bSMauro Carvalho Chehabdescribes the UDC transceiver with a name and id number.
4734ad4b21bSMauro Carvalho Chehab
47467cc20e0SMauro Carvalho ChehabAt the time of this writing, note that ``usb_phy_gen_xceiv`` is the
4754ad4b21bSMauro Carvalho Chehabspecific name to be used for all transceivers that are either built-in
4764ad4b21bSMauro Carvalho Chehabwith reference USB IP or autonomous and doesn't require any PHY
47767cc20e0SMauro Carvalho Chehabprogramming. You will need to set ``CONFIG_NOP_USB_XCEIV=y`` in the
4784ad4b21bSMauro Carvalho Chehabkernel configuration to make use of the corresponding transceiver
4794ad4b21bSMauro Carvalho Chehabdriver. The id field could be set to -1 (equivalent to
48067cc20e0SMauro Carvalho Chehab``PLATFORM_DEVID_NONE``), -2 (equivalent to ``PLATFORM_DEVID_AUTO``) or
4814ad4b21bSMauro Carvalho Chehabstart with 0 for the first device of this kind if we want a specific id
4824ad4b21bSMauro Carvalho Chehabnumber.
4834ad4b21bSMauro Carvalho Chehab
48467cc20e0SMauro Carvalho ChehabThe ``jz4740_udc_resources`` resource structure (line 7) defines the UDC
4854ad4b21bSMauro Carvalho Chehabregisters base addresses.
4864ad4b21bSMauro Carvalho Chehab
4874ad4b21bSMauro Carvalho ChehabThe first array (line 9 to 11) defines the UDC registers base memory
4884ad4b21bSMauro Carvalho Chehabaddresses: start points to the first register memory address, end points
4894ad4b21bSMauro Carvalho Chehabto the last register memory address and the flags member defines the
49067cc20e0SMauro Carvalho Chehabtype of resource we are dealing with. So ``IORESOURCE_MEM`` is used to
4914ad4b21bSMauro Carvalho Chehabdefine the registers memory addresses. The second array (line 14 to 17)
4924ad4b21bSMauro Carvalho Chehabdefines the UDC IRQ registers addresses. Since there is only one IRQ
4934ad4b21bSMauro Carvalho Chehabregister available for the JZ4740 UDC, start and end point at the same
49467cc20e0SMauro Carvalho Chehabaddress. The ``IORESOURCE_IRQ`` flag tells that we are dealing with IRQ
49567cc20e0SMauro Carvalho Chehabresources, and the name ``mc`` is in fact hard-coded in the MUSB core in
4964ad4b21bSMauro Carvalho Chehaborder for the controller driver to retrieve this IRQ resource by
4974ad4b21bSMauro Carvalho Chehabquerying it by its name.
4984ad4b21bSMauro Carvalho Chehab
49967cc20e0SMauro Carvalho ChehabFinally, the ``jz4740_udc_device`` platform device structure (line 21)
5004ad4b21bSMauro Carvalho Chehabdescribes the UDC itself.
5014ad4b21bSMauro Carvalho Chehab
50267cc20e0SMauro Carvalho ChehabThe ``musb-jz4740`` name (line 22) defines the MUSB driver that is used
5034ad4b21bSMauro Carvalho Chehabfor this device; remember this is in fact the name that we used in the
50467cc20e0SMauro Carvalho Chehab``jz4740_driver`` platform driver structure in :ref:`musb-basics`.
50567cc20e0SMauro Carvalho ChehabThe id field (line 23) is set to -1 (equivalent to ``PLATFORM_DEVID_NONE``)
50667cc20e0SMauro Carvalho Chehabsince we do not need an id for the device: the MUSB controller driver was
50767cc20e0SMauro Carvalho Chehabalready set to allocate an automatic id in :ref:`musb-basics`. In the dev field
50867cc20e0SMauro Carvalho Chehabwe care for DMA related information here. The ``dma_mask`` field (line 25)
5094ad4b21bSMauro Carvalho Chehabdefines the width of the DMA mask that is going to be used, and
51067cc20e0SMauro Carvalho Chehab``coherent_dma_mask`` (line 26) has the same purpose but for the
51167cc20e0SMauro Carvalho Chehab``alloc_coherent`` DMA mappings: in both cases we are using a 32 bits mask.
5124ad4b21bSMauro Carvalho ChehabThen the resource field (line 29) is simply a pointer to the resource
51367cc20e0SMauro Carvalho Chehabstructure defined before, while the ``num_resources`` field (line 28) keeps
5144ad4b21bSMauro Carvalho Chehabtrack of the number of arrays defined in the resource structure (in this
5154ad4b21bSMauro Carvalho Chehabcase there were two resource arrays defined before).
5164ad4b21bSMauro Carvalho Chehab
51767cc20e0SMauro Carvalho ChehabWith this quick overview of the UDC platform data at the ``arch/`` level now
5184ad4b21bSMauro Carvalho Chehabdone, let's get back to the MUSB glue layer specific platform data in
51967cc20e0SMauro Carvalho Chehab``drivers/usb/musb/jz4740.c``:
5204ad4b21bSMauro Carvalho Chehab
52167cc20e0SMauro Carvalho Chehab   .. code-block:: c
52267cc20e0SMauro Carvalho Chehab    :emphasize-lines: 3,5,7-9,11
5234ad4b21bSMauro Carvalho Chehab
5244ad4b21bSMauro Carvalho Chehab    static struct musb_hdrc_config jz4740_musb_config = {
5254ad4b21bSMauro Carvalho Chehab	/* Silicon does not implement USB OTG. */
5264ad4b21bSMauro Carvalho Chehab	.multipoint = 0,
5274ad4b21bSMauro Carvalho Chehab	/* Max EPs scanned, driver will decide which EP can be used. */
5284ad4b21bSMauro Carvalho Chehab	.num_eps    = 4,
5294ad4b21bSMauro Carvalho Chehab	/* RAMbits needed to configure EPs from table */
5304ad4b21bSMauro Carvalho Chehab	.ram_bits   = 9,
5314ad4b21bSMauro Carvalho Chehab	.fifo_cfg = jz4740_musb_fifo_cfg,
5324ad4b21bSMauro Carvalho Chehab	.fifo_cfg_size = ARRAY_SIZE(jz4740_musb_fifo_cfg),
5334ad4b21bSMauro Carvalho Chehab    };
5344ad4b21bSMauro Carvalho Chehab
5354ad4b21bSMauro Carvalho Chehab    static struct musb_hdrc_platform_data jz4740_musb_platform_data = {
5364ad4b21bSMauro Carvalho Chehab	.mode   = MUSB_PERIPHERAL,
5374ad4b21bSMauro Carvalho Chehab	.config = &jz4740_musb_config,
5384ad4b21bSMauro Carvalho Chehab    };
5394ad4b21bSMauro Carvalho Chehab
5404ad4b21bSMauro Carvalho ChehabFirst the glue layer configures some aspects of the controller driver
5414ad4b21bSMauro Carvalho Chehaboperation related to the controller hardware specifics. This is done
54267cc20e0SMauro Carvalho Chehabthrough the ``jz4740_musb_config`` :c:type:`musb_hdrc_config` structure.
5434ad4b21bSMauro Carvalho Chehab
5444ad4b21bSMauro Carvalho ChehabDefining the OTG capability of the controller hardware, the multipoint
5454ad4b21bSMauro Carvalho Chehabmember (line 3) is set to 0 (equivalent to false) since the JZ4740 UDC
54667cc20e0SMauro Carvalho Chehabis not OTG compatible. Then ``num_eps`` (line 5) defines the number of USB
5474ad4b21bSMauro Carvalho Chehabendpoints of the controller hardware, including endpoint 0: here we have
54867cc20e0SMauro Carvalho Chehab3 endpoints + endpoint 0. Next is ``ram_bits`` (line 7) which is the width
5494ad4b21bSMauro Carvalho Chehabof the RAM address bus for the MUSB controller hardware. This
5504ad4b21bSMauro Carvalho Chehabinformation is needed when the controller driver cannot automatically
5514ad4b21bSMauro Carvalho Chehabconfigure endpoints by reading the relevant controller hardware
5524ad4b21bSMauro Carvalho Chehabregisters. This issue will be discussed when we get to device quirks in
55367cc20e0SMauro Carvalho Chehab:ref:`musb-dev-quirks`. Last two fields (line 8 and 9) are also
55467cc20e0SMauro Carvalho Chehababout device quirks: ``fifo_cfg`` points to the USB endpoints configuration
55567cc20e0SMauro Carvalho Chehabtable and ``fifo_cfg_size`` keeps track of the size of the number of
55667cc20e0SMauro Carvalho Chehabentries in that configuration table. More on that later in
55767cc20e0SMauro Carvalho Chehab:ref:`musb-dev-quirks`.
5584ad4b21bSMauro Carvalho Chehab
55967cc20e0SMauro Carvalho ChehabThen this configuration is embedded inside ``jz4740_musb_platform_data``
56067cc20e0SMauro Carvalho Chehab:c:type:`musb_hdrc_platform_data` structure (line 11): config is a pointer to
5614ad4b21bSMauro Carvalho Chehabthe configuration structure itself, and mode tells the controller driver
56267cc20e0SMauro Carvalho Chehabif the controller hardware may be used as ``MUSB_HOST`` only,
56367cc20e0SMauro Carvalho Chehab``MUSB_PERIPHERAL`` only or ``MUSB_OTG`` which is a dual mode.
5644ad4b21bSMauro Carvalho Chehab
56567cc20e0SMauro Carvalho ChehabRemember that ``jz4740_musb_platform_data`` is then used to convey
5664ad4b21bSMauro Carvalho Chehabplatform data information as we have seen in the probe function in
56767cc20e0SMauro Carvalho Chehab:ref:`musb-basics`.
56867cc20e0SMauro Carvalho Chehab
56967cc20e0SMauro Carvalho Chehab.. _musb-dev-quirks:
5704ad4b21bSMauro Carvalho Chehab
5714ad4b21bSMauro Carvalho ChehabDevice Quirks
5724ad4b21bSMauro Carvalho Chehab=============
5734ad4b21bSMauro Carvalho Chehab
5744ad4b21bSMauro Carvalho ChehabCompleting the platform data specific to your device, you may also need
5754ad4b21bSMauro Carvalho Chehabto write some code in the glue layer to work around some device specific
5764ad4b21bSMauro Carvalho Chehablimitations. These quirks may be due to some hardware bugs, or simply be
5774ad4b21bSMauro Carvalho Chehabthe result of an incomplete implementation of the USB On-the-Go
5784ad4b21bSMauro Carvalho Chehabspecification.
5794ad4b21bSMauro Carvalho Chehab
5804ad4b21bSMauro Carvalho ChehabThe JZ4740 UDC exhibits such quirks, some of which we will discuss here
5814ad4b21bSMauro Carvalho Chehabfor the sake of insight even though these might not be found in the
5824ad4b21bSMauro Carvalho Chehabcontroller hardware you are working on.
5834ad4b21bSMauro Carvalho Chehab
5844ad4b21bSMauro Carvalho ChehabLet's get back to the init function first:
5854ad4b21bSMauro Carvalho Chehab
58667cc20e0SMauro Carvalho Chehab   .. code-block:: c
58767cc20e0SMauro Carvalho Chehab    :emphasize-lines: 12
5884ad4b21bSMauro Carvalho Chehab
5894ad4b21bSMauro Carvalho Chehab    static int jz4740_musb_init(struct musb *musb)
5904ad4b21bSMauro Carvalho Chehab    {
5914ad4b21bSMauro Carvalho Chehab	musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2);
5924ad4b21bSMauro Carvalho Chehab	if (!musb->xceiv) {
5934ad4b21bSMauro Carvalho Chehab	    pr_err("HS UDC: no transceiver configured\n");
5944ad4b21bSMauro Carvalho Chehab	    return -ENODEV;
5954ad4b21bSMauro Carvalho Chehab	}
5964ad4b21bSMauro Carvalho Chehab
5974ad4b21bSMauro Carvalho Chehab	/* Silicon does not implement ConfigData register.
5984ad4b21bSMauro Carvalho Chehab	 * Set dyn_fifo to avoid reading EP config from hardware.
5994ad4b21bSMauro Carvalho Chehab	 */
6004ad4b21bSMauro Carvalho Chehab	musb->dyn_fifo = true;
6014ad4b21bSMauro Carvalho Chehab
6024ad4b21bSMauro Carvalho Chehab	musb->isr = jz4740_musb_interrupt;
6034ad4b21bSMauro Carvalho Chehab
6044ad4b21bSMauro Carvalho Chehab	return 0;
6054ad4b21bSMauro Carvalho Chehab    }
6064ad4b21bSMauro Carvalho Chehab
6074ad4b21bSMauro Carvalho ChehabInstruction on line 12 helps the MUSB controller driver to work around
6084ad4b21bSMauro Carvalho Chehabthe fact that the controller hardware is missing registers that are used
6094ad4b21bSMauro Carvalho Chehabfor USB endpoints configuration.
6104ad4b21bSMauro Carvalho Chehab
6114ad4b21bSMauro Carvalho ChehabWithout these registers, the controller driver is unable to read the
6124ad4b21bSMauro Carvalho Chehabendpoints configuration from the hardware, so we use line 12 instruction
6134ad4b21bSMauro Carvalho Chehabto bypass reading the configuration from silicon, and rely on a
61467cc20e0SMauro Carvalho Chehabhard-coded table that describes the endpoints configuration instead::
6154ad4b21bSMauro Carvalho Chehab
6164ad4b21bSMauro Carvalho Chehab    static struct musb_fifo_cfg jz4740_musb_fifo_cfg[] = {
6174ad4b21bSMauro Carvalho Chehab	{ .hw_ep_num = 1, .style = FIFO_TX, .maxpacket = 512, },
6184ad4b21bSMauro Carvalho Chehab	{ .hw_ep_num = 1, .style = FIFO_RX, .maxpacket = 512, },
6194ad4b21bSMauro Carvalho Chehab	{ .hw_ep_num = 2, .style = FIFO_TX, .maxpacket = 64, },
6204ad4b21bSMauro Carvalho Chehab    };
6214ad4b21bSMauro Carvalho Chehab
6224ad4b21bSMauro Carvalho ChehabLooking at the configuration table above, we see that each endpoints is
62367cc20e0SMauro Carvalho Chehabdescribed by three fields: ``hw_ep_num`` is the endpoint number, style is
62467cc20e0SMauro Carvalho Chehabits direction (either ``FIFO_TX`` for the controller driver to send packets
62567cc20e0SMauro Carvalho Chehabin the controller hardware, or ``FIFO_RX`` to receive packets from
6264ad4b21bSMauro Carvalho Chehabhardware), and maxpacket defines the maximum size of each data packet
6274ad4b21bSMauro Carvalho Chehabthat can be transmitted over that endpoint. Reading from the table, the
6284ad4b21bSMauro Carvalho Chehabcontroller driver knows that endpoint 1 can be used to send and receive
6294ad4b21bSMauro Carvalho ChehabUSB data packets of 512 bytes at once (this is in fact a bulk in/out
6304ad4b21bSMauro Carvalho Chehabendpoint), and endpoint 2 can be used to send data packets of 64 bytes
6314ad4b21bSMauro Carvalho Chehabat once (this is in fact an interrupt endpoint).
6324ad4b21bSMauro Carvalho Chehab
6334ad4b21bSMauro Carvalho ChehabNote that there is no information about endpoint 0 here: that one is
6344ad4b21bSMauro Carvalho Chehabimplemented by default in every silicon design, with a predefined
6354ad4b21bSMauro Carvalho Chehabconfiguration according to the USB specification. For more examples of
63667cc20e0SMauro Carvalho Chehabendpoint configuration tables, see ``musb_core.c``.
6374ad4b21bSMauro Carvalho Chehab
6384ad4b21bSMauro Carvalho ChehabLet's now get back to the interrupt handler function:
6394ad4b21bSMauro Carvalho Chehab
64067cc20e0SMauro Carvalho Chehab   .. code-block:: c
64167cc20e0SMauro Carvalho Chehab    :emphasize-lines: 18-19
6424ad4b21bSMauro Carvalho Chehab
6434ad4b21bSMauro Carvalho Chehab    static irqreturn_t jz4740_musb_interrupt(int irq, void *__hci)
6444ad4b21bSMauro Carvalho Chehab    {
6454ad4b21bSMauro Carvalho Chehab	unsigned long   flags;
6464ad4b21bSMauro Carvalho Chehab	irqreturn_t     retval = IRQ_NONE;
6474ad4b21bSMauro Carvalho Chehab	struct musb     *musb = __hci;
6484ad4b21bSMauro Carvalho Chehab
6494ad4b21bSMauro Carvalho Chehab	spin_lock_irqsave(&musb->lock, flags);
6504ad4b21bSMauro Carvalho Chehab
6514ad4b21bSMauro Carvalho Chehab	musb->int_usb = musb_readb(musb->mregs, MUSB_INTRUSB);
6524ad4b21bSMauro Carvalho Chehab	musb->int_tx = musb_readw(musb->mregs, MUSB_INTRTX);
6534ad4b21bSMauro Carvalho Chehab	musb->int_rx = musb_readw(musb->mregs, MUSB_INTRRX);
6544ad4b21bSMauro Carvalho Chehab
6554ad4b21bSMauro Carvalho Chehab	/*
6564ad4b21bSMauro Carvalho Chehab	 * The controller is gadget only, the state of the host mode IRQ bits is
6574ad4b21bSMauro Carvalho Chehab	 * undefined. Mask them to make sure that the musb driver core will
6584ad4b21bSMauro Carvalho Chehab	 * never see them set
6594ad4b21bSMauro Carvalho Chehab	 */
6604ad4b21bSMauro Carvalho Chehab	musb->int_usb &= MUSB_INTR_SUSPEND | MUSB_INTR_RESUME |
6614ad4b21bSMauro Carvalho Chehab	    MUSB_INTR_RESET | MUSB_INTR_SOF;
6624ad4b21bSMauro Carvalho Chehab
6634ad4b21bSMauro Carvalho Chehab	if (musb->int_usb || musb->int_tx || musb->int_rx)
6644ad4b21bSMauro Carvalho Chehab	    retval = musb_interrupt(musb);
6654ad4b21bSMauro Carvalho Chehab
6664ad4b21bSMauro Carvalho Chehab	spin_unlock_irqrestore(&musb->lock, flags);
6674ad4b21bSMauro Carvalho Chehab
6684ad4b21bSMauro Carvalho Chehab	return retval;
6694ad4b21bSMauro Carvalho Chehab    }
6704ad4b21bSMauro Carvalho Chehab
6714ad4b21bSMauro Carvalho ChehabInstruction on line 18 above is a way for the controller driver to work
6724ad4b21bSMauro Carvalho Chehabaround the fact that some interrupt bits used for USB host mode
67367cc20e0SMauro Carvalho Chehaboperation are missing in the ``MUSB_INTRUSB`` register, thus left in an
6744ad4b21bSMauro Carvalho Chehabundefined hardware state, since this MUSB controller hardware is used in
6754ad4b21bSMauro Carvalho Chehabperipheral mode only. As a consequence, the glue layer masks these
6764ad4b21bSMauro Carvalho Chehabmissing bits out to avoid parasite interrupts by doing a logical AND
67767cc20e0SMauro Carvalho Chehaboperation between the value read from ``MUSB_INTRUSB`` and the bits that
6784ad4b21bSMauro Carvalho Chehabare actually implemented in the register.
6794ad4b21bSMauro Carvalho Chehab
6804ad4b21bSMauro Carvalho ChehabThese are only a couple of the quirks found in the JZ4740 USB device
6814ad4b21bSMauro Carvalho Chehabcontroller. Some others were directly addressed in the MUSB core since
6824ad4b21bSMauro Carvalho Chehabthe fixes were generic enough to provide a better handling of the issues
6834ad4b21bSMauro Carvalho Chehabfor others controller hardware eventually.
6844ad4b21bSMauro Carvalho Chehab
6854ad4b21bSMauro Carvalho ChehabConclusion
6864ad4b21bSMauro Carvalho Chehab==========
6874ad4b21bSMauro Carvalho Chehab
6884ad4b21bSMauro Carvalho ChehabWriting a Linux MUSB glue layer should be a more accessible task, as
6894ad4b21bSMauro Carvalho Chehabthis documentation tries to show the ins and outs of this exercise.
6904ad4b21bSMauro Carvalho Chehab
6914ad4b21bSMauro Carvalho ChehabThe JZ4740 USB device controller being fairly simple, I hope its glue
6924ad4b21bSMauro Carvalho Chehablayer serves as a good example for the curious mind. Used with the
6934ad4b21bSMauro Carvalho Chehabcurrent MUSB glue layers, this documentation should provide enough
6944ad4b21bSMauro Carvalho Chehabguidance to get started; should anything gets out of hand, the linux-usb
6954ad4b21bSMauro Carvalho Chehabmailing list archive is another helpful resource to browse through.
6964ad4b21bSMauro Carvalho Chehab
6974ad4b21bSMauro Carvalho ChehabAcknowledgements
6984ad4b21bSMauro Carvalho Chehab================
6994ad4b21bSMauro Carvalho Chehab
7004ad4b21bSMauro Carvalho ChehabMany thanks to Lars-Peter Clausen and Maarten ter Huurne for answering
7014ad4b21bSMauro Carvalho Chehabmy questions while I was writing the JZ4740 glue layer and for helping
7024ad4b21bSMauro Carvalho Chehabme out getting the code in good shape.
7034ad4b21bSMauro Carvalho Chehab
7044ad4b21bSMauro Carvalho ChehabI would also like to thank the Qi-Hardware community at large for its
7054ad4b21bSMauro Carvalho Chehabcheerful guidance and support.
7064ad4b21bSMauro Carvalho Chehab
7074ad4b21bSMauro Carvalho ChehabResources
7084ad4b21bSMauro Carvalho Chehab=========
7094ad4b21bSMauro Carvalho Chehab
710*93431e06SAlexander A. KlimovUSB Home Page: https://www.usb.org
7114ad4b21bSMauro Carvalho Chehab
712*93431e06SAlexander A. Klimovlinux-usb Mailing List Archives: https://marc.info/?l=linux-usb
7134ad4b21bSMauro Carvalho Chehab
7144ad4b21bSMauro Carvalho ChehabUSB On-the-Go Basics:
715*93431e06SAlexander A. Klimovhttps://www.maximintegrated.com/app-notes/index.mvp/id/1822
7164ad4b21bSMauro Carvalho Chehab
71767cc20e0SMauro Carvalho Chehab:ref:`Writing USB Device Drivers <writing-usb-driver>`
7184ad4b21bSMauro Carvalho Chehab
7194ad4b21bSMauro Carvalho ChehabTexas Instruments USB Configuration Wiki Page:
7204ad4b21bSMauro Carvalho Chehabhttp://processors.wiki.ti.com/index.php/Usbgeneralpage
721