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 Chehab ⬍ 524ad4b21bSMauro 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 Chehab ⬍ 584ad4b21bSMauro 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 Chehab ⬍ 644ad4b21bSMauro 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