0001 =========================
0002 Writing a MUSB Glue Layer
0003 =========================
0004
0005 :Author: Apelete Seketeli
0006
0007 Introduction
0008 ============
0009
0010 The Linux MUSB subsystem is part of the larger Linux USB subsystem. It
0011 provides support for embedded USB Device Controllers (UDC) that do not
0012 use Universal Host Controller Interface (UHCI) or Open Host Controller
0013 Interface (OHCI).
0014
0015 Instead, these embedded UDC rely on the USB On-the-Go (OTG)
0016 specification which they implement at least partially. The silicon
0017 reference design used in most cases is the Multipoint USB Highspeed
0018 Dual-Role Controller (MUSB HDRC) found in the Mentor Graphics Inventra™
0019 design.
0020
0021 As a self-taught exercise I have written an MUSB glue layer for the
0022 Ingenic JZ4740 SoC, modelled after the many MUSB glue layers in the
0023 kernel source tree. This layer can be found at
0024 ``drivers/usb/musb/jz4740.c``. In this documentation I will walk through the
0025 basics of the ``jz4740.c`` glue layer, explaining the different pieces and
0026 what needs to be done in order to write your own device glue layer.
0027
0028 .. _musb-basics:
0029
0030 Linux MUSB Basics
0031 =================
0032
0033 To get started on the topic, please read USB On-the-Go Basics (see
0034 Resources) which provides an introduction of USB OTG operation at the
0035 hardware level. A couple of wiki pages by Texas Instruments and Analog
0036 Devices also provide an overview of the Linux kernel MUSB configuration,
0037 albeit focused on some specific devices provided by these companies.
0038 Finally, getting acquainted with the USB specification at USB home page
0039 may come in handy, with practical instance provided through the Writing
0040 USB Device Drivers documentation (again, see Resources).
0041
0042 Linux USB stack is a layered architecture in which the MUSB controller
0043 hardware sits at the lowest. The MUSB controller driver abstract the
0044 MUSB controller hardware to the Linux USB stack::
0045
0046 ------------------------
0047 | | <------- drivers/usb/gadget
0048 | Linux USB Core Stack | <------- drivers/usb/host
0049 | | <------- drivers/usb/core
0050 ------------------------
0051 ⬍
0052 --------------------------
0053 | | <------ drivers/usb/musb/musb_gadget.c
0054 | MUSB Controller driver | <------ drivers/usb/musb/musb_host.c
0055 | | <------ drivers/usb/musb/musb_core.c
0056 --------------------------
0057 ⬍
0058 ---------------------------------
0059 | MUSB Platform Specific Driver |
0060 | | <-- drivers/usb/musb/jz4740.c
0061 | aka "Glue Layer" |
0062 ---------------------------------
0063 ⬍
0064 ---------------------------------
0065 | MUSB Controller Hardware |
0066 ---------------------------------
0067
0068 As outlined above, the glue layer is actually the platform specific code
0069 sitting in between the controller driver and the controller hardware.
0070
0071 Just like a Linux USB driver needs to register itself with the Linux USB
0072 subsystem, the MUSB glue layer needs first to register itself with the
0073 MUSB controller driver. This will allow the controller driver to know
0074 about which device the glue layer supports and which functions to call
0075 when a supported device is detected or released; remember we are talking
0076 about an embedded controller chip here, so no insertion or removal at
0077 run-time.
0078
0079 All of this information is passed to the MUSB controller driver through
0080 a :c:type:`platform_driver` structure defined in the glue layer as::
0081
0082 static struct platform_driver jz4740_driver = {
0083 .probe = jz4740_probe,
0084 .remove = jz4740_remove,
0085 .driver = {
0086 .name = "musb-jz4740",
0087 },
0088 };
0089
0090 The probe and remove function pointers are called when a matching device
0091 is detected and, respectively, released. The name string describes the
0092 device supported by this glue layer. In the current case it matches a
0093 platform_device structure declared in ``arch/mips/jz4740/platform.c``. Note
0094 that we are not using device tree bindings here.
0095
0096 In order to register itself to the controller driver, the glue layer
0097 goes through a few steps, basically allocating the controller hardware
0098 resources and initialising a couple of circuits. To do so, it needs to
0099 keep track of the information used throughout these steps. This is done
0100 by defining a private ``jz4740_glue`` structure::
0101
0102 struct jz4740_glue {
0103 struct device *dev;
0104 struct platform_device *musb;
0105 struct clk *clk;
0106 };
0107
0108
0109 The dev and musb members are both device structure variables. The first
0110 one holds generic information about the device, since it's the basic
0111 device structure, and the latter holds information more closely related
0112 to the subsystem the device is registered to. The clk variable keeps
0113 information related to the device clock operation.
0114
0115 Let's go through the steps of the probe function that leads the glue
0116 layer to register itself to the controller driver.
0117
0118 .. note::
0119
0120 For the sake of readability each function will be split in logical
0121 parts, each part being shown as if it was independent from the others.
0122
0123 .. code-block:: c
0124 :emphasize-lines: 8,12,18
0125
0126 static int jz4740_probe(struct platform_device *pdev)
0127 {
0128 struct platform_device *musb;
0129 struct jz4740_glue *glue;
0130 struct clk *clk;
0131 int ret;
0132
0133 glue = devm_kzalloc(&pdev->dev, sizeof(*glue), GFP_KERNEL);
0134 if (!glue)
0135 return -ENOMEM;
0136
0137 musb = platform_device_alloc("musb-hdrc", PLATFORM_DEVID_AUTO);
0138 if (!musb) {
0139 dev_err(&pdev->dev, "failed to allocate musb device\n");
0140 return -ENOMEM;
0141 }
0142
0143 clk = devm_clk_get(&pdev->dev, "udc");
0144 if (IS_ERR(clk)) {
0145 dev_err(&pdev->dev, "failed to get clock\n");
0146 ret = PTR_ERR(clk);
0147 goto err_platform_device_put;
0148 }
0149
0150 ret = clk_prepare_enable(clk);
0151 if (ret) {
0152 dev_err(&pdev->dev, "failed to enable clock\n");
0153 goto err_platform_device_put;
0154 }
0155
0156 musb->dev.parent = &pdev->dev;
0157
0158 glue->dev = &pdev->dev;
0159 glue->musb = musb;
0160 glue->clk = clk;
0161
0162 return 0;
0163
0164 err_platform_device_put:
0165 platform_device_put(musb);
0166 return ret;
0167 }
0168
0169 The first few lines of the probe function allocate and assign the glue,
0170 musb and clk variables. The ``GFP_KERNEL`` flag (line 8) allows the
0171 allocation process to sleep and wait for memory, thus being usable in a
0172 locking situation. The ``PLATFORM_DEVID_AUTO`` flag (line 12) allows
0173 automatic allocation and management of device IDs in order to avoid
0174 device namespace collisions with explicit IDs. With :c:func:`devm_clk_get`
0175 (line 18) the glue layer allocates the clock -- the ``devm_`` prefix
0176 indicates that :c:func:`clk_get` is managed: it automatically frees the
0177 allocated clock resource data when the device is released -- and enable
0178 it.
0179
0180
0181
0182 Then comes the registration steps:
0183
0184 .. code-block:: c
0185 :emphasize-lines: 3,5,7,9,16
0186
0187 static int jz4740_probe(struct platform_device *pdev)
0188 {
0189 struct musb_hdrc_platform_data *pdata = &jz4740_musb_platform_data;
0190
0191 pdata->platform_ops = &jz4740_musb_ops;
0192
0193 platform_set_drvdata(pdev, glue);
0194
0195 ret = platform_device_add_resources(musb, pdev->resource,
0196 pdev->num_resources);
0197 if (ret) {
0198 dev_err(&pdev->dev, "failed to add resources\n");
0199 goto err_clk_disable;
0200 }
0201
0202 ret = platform_device_add_data(musb, pdata, sizeof(*pdata));
0203 if (ret) {
0204 dev_err(&pdev->dev, "failed to add platform_data\n");
0205 goto err_clk_disable;
0206 }
0207
0208 return 0;
0209
0210 err_clk_disable:
0211 clk_disable_unprepare(clk);
0212 err_platform_device_put:
0213 platform_device_put(musb);
0214 return ret;
0215 }
0216
0217 The first step is to pass the device data privately held by the glue
0218 layer on to the controller driver through :c:func:`platform_set_drvdata`
0219 (line 7). Next is passing on the device resources information, also privately
0220 held at that point, through :c:func:`platform_device_add_resources` (line 9).
0221
0222 Finally comes passing on the platform specific data to the controller
0223 driver (line 16). Platform data will be discussed in
0224 :ref:`musb-dev-platform-data`, but here we are looking at the
0225 ``platform_ops`` function pointer (line 5) in ``musb_hdrc_platform_data``
0226 structure (line 3). This function pointer allows the MUSB controller
0227 driver to know which function to call for device operation::
0228
0229 static const struct musb_platform_ops jz4740_musb_ops = {
0230 .init = jz4740_musb_init,
0231 .exit = jz4740_musb_exit,
0232 };
0233
0234 Here we have the minimal case where only init and exit functions are
0235 called by the controller driver when needed. Fact is the JZ4740 MUSB
0236 controller is a basic controller, lacking some features found in other
0237 controllers, otherwise we may also have pointers to a few other
0238 functions like a power management function or a function to switch
0239 between OTG and non-OTG modes, for instance.
0240
0241 At that point of the registration process, the controller driver
0242 actually calls the init function:
0243
0244 .. code-block:: c
0245 :emphasize-lines: 12,14
0246
0247 static int jz4740_musb_init(struct musb *musb)
0248 {
0249 musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2);
0250 if (!musb->xceiv) {
0251 pr_err("HS UDC: no transceiver configured\n");
0252 return -ENODEV;
0253 }
0254
0255 /* Silicon does not implement ConfigData register.
0256 * Set dyn_fifo to avoid reading EP config from hardware.
0257 */
0258 musb->dyn_fifo = true;
0259
0260 musb->isr = jz4740_musb_interrupt;
0261
0262 return 0;
0263 }
0264
0265 The goal of ``jz4740_musb_init()`` is to get hold of the transceiver
0266 driver data of the MUSB controller hardware and pass it on to the MUSB
0267 controller driver, as usual. The transceiver is the circuitry inside the
0268 controller hardware responsible for sending/receiving the USB data.
0269 Since it is an implementation of the physical layer of the OSI model,
0270 the transceiver is also referred to as PHY.
0271
0272 Getting hold of the ``MUSB PHY`` driver data is done with ``usb_get_phy()``
0273 which returns a pointer to the structure containing the driver instance
0274 data. The next couple of instructions (line 12 and 14) are used as a
0275 quirk and to setup IRQ handling respectively. Quirks and IRQ handling
0276 will be discussed later in :ref:`musb-dev-quirks` and
0277 :ref:`musb-handling-irqs`\ ::
0278
0279 static int jz4740_musb_exit(struct musb *musb)
0280 {
0281 usb_put_phy(musb->xceiv);
0282
0283 return 0;
0284 }
0285
0286 Acting as the counterpart of init, the exit function releases the MUSB
0287 PHY driver when the controller hardware itself is about to be released.
0288
0289 Again, note that init and exit are fairly simple in this case due to the
0290 basic set of features of the JZ4740 controller hardware. When writing an
0291 musb glue layer for a more complex controller hardware, you might need
0292 to take care of more processing in those two functions.
0293
0294 Returning from the init function, the MUSB controller driver jumps back
0295 into the probe function::
0296
0297 static int jz4740_probe(struct platform_device *pdev)
0298 {
0299 ret = platform_device_add(musb);
0300 if (ret) {
0301 dev_err(&pdev->dev, "failed to register musb device\n");
0302 goto err_clk_disable;
0303 }
0304
0305 return 0;
0306
0307 err_clk_disable:
0308 clk_disable_unprepare(clk);
0309 err_platform_device_put:
0310 platform_device_put(musb);
0311 return ret;
0312 }
0313
0314 This is the last part of the device registration process where the glue
0315 layer adds the controller hardware device to Linux kernel device
0316 hierarchy: at this stage, all known information about the device is
0317 passed on to the Linux USB core stack:
0318
0319 .. code-block:: c
0320 :emphasize-lines: 5,6
0321
0322 static int jz4740_remove(struct platform_device *pdev)
0323 {
0324 struct jz4740_glue *glue = platform_get_drvdata(pdev);
0325
0326 platform_device_unregister(glue->musb);
0327 clk_disable_unprepare(glue->clk);
0328
0329 return 0;
0330 }
0331
0332 Acting as the counterpart of probe, the remove function unregister the
0333 MUSB controller hardware (line 5) and disable the clock (line 6),
0334 allowing it to be gated.
0335
0336 .. _musb-handling-irqs:
0337
0338 Handling IRQs
0339 =============
0340
0341 Additionally to the MUSB controller hardware basic setup and
0342 registration, the glue layer is also responsible for handling the IRQs:
0343
0344 .. code-block:: c
0345 :emphasize-lines: 7,9-11,14,24
0346
0347 static irqreturn_t jz4740_musb_interrupt(int irq, void *__hci)
0348 {
0349 unsigned long flags;
0350 irqreturn_t retval = IRQ_NONE;
0351 struct musb *musb = __hci;
0352
0353 spin_lock_irqsave(&musb->lock, flags);
0354
0355 musb->int_usb = musb_readb(musb->mregs, MUSB_INTRUSB);
0356 musb->int_tx = musb_readw(musb->mregs, MUSB_INTRTX);
0357 musb->int_rx = musb_readw(musb->mregs, MUSB_INTRRX);
0358
0359 /*
0360 * The controller is gadget only, the state of the host mode IRQ bits is
0361 * undefined. Mask them to make sure that the musb driver core will
0362 * never see them set
0363 */
0364 musb->int_usb &= MUSB_INTR_SUSPEND | MUSB_INTR_RESUME |
0365 MUSB_INTR_RESET | MUSB_INTR_SOF;
0366
0367 if (musb->int_usb || musb->int_tx || musb->int_rx)
0368 retval = musb_interrupt(musb);
0369
0370 spin_unlock_irqrestore(&musb->lock, flags);
0371
0372 return retval;
0373 }
0374
0375 Here the glue layer mostly has to read the relevant hardware registers
0376 and pass their values on to the controller driver which will handle the
0377 actual event that triggered the IRQ.
0378
0379 The interrupt handler critical section is protected by the
0380 :c:func:`spin_lock_irqsave` and counterpart :c:func:`spin_unlock_irqrestore`
0381 functions (line 7 and 24 respectively), which prevent the interrupt
0382 handler code to be run by two different threads at the same time.
0383
0384 Then the relevant interrupt registers are read (line 9 to 11):
0385
0386 - ``MUSB_INTRUSB``: indicates which USB interrupts are currently active,
0387
0388 - ``MUSB_INTRTX``: indicates which of the interrupts for TX endpoints are
0389 currently active,
0390
0391 - ``MUSB_INTRRX``: indicates which of the interrupts for TX endpoints are
0392 currently active.
0393
0394 Note that :c:func:`musb_readb` is used to read 8-bit registers at most, while
0395 :c:func:`musb_readw` allows us to read at most 16-bit registers. There are
0396 other functions that can be used depending on the size of your device
0397 registers. See ``musb_io.h`` for more information.
0398
0399 Instruction on line 18 is another quirk specific to the JZ4740 USB
0400 device controller, which will be discussed later in :ref:`musb-dev-quirks`.
0401
0402 The glue layer still needs to register the IRQ handler though. Remember
0403 the instruction on line 14 of the init function::
0404
0405 static int jz4740_musb_init(struct musb *musb)
0406 {
0407 musb->isr = jz4740_musb_interrupt;
0408
0409 return 0;
0410 }
0411
0412 This instruction sets a pointer to the glue layer IRQ handler function,
0413 in order for the controller hardware to call the handler back when an
0414 IRQ comes from the controller hardware. The interrupt handler is now
0415 implemented and registered.
0416
0417 .. _musb-dev-platform-data:
0418
0419 Device Platform Data
0420 ====================
0421
0422 In order to write an MUSB glue layer, you need to have some data
0423 describing the hardware capabilities of your controller hardware, which
0424 is called the platform data.
0425
0426 Platform data is specific to your hardware, though it may cover a broad
0427 range of devices, and is generally found somewhere in the ``arch/``
0428 directory, depending on your device architecture.
0429
0430 For instance, platform data for the JZ4740 SoC is found in
0431 ``arch/mips/jz4740/platform.c``. In the ``platform.c`` file each device of the
0432 JZ4740 SoC is described through a set of structures.
0433
0434 Here is the part of ``arch/mips/jz4740/platform.c`` that covers the USB
0435 Device Controller (UDC):
0436
0437 .. code-block:: c
0438 :emphasize-lines: 2,7,14-17,21,22,25,26,28,29
0439
0440 /* USB Device Controller */
0441 struct platform_device jz4740_udc_xceiv_device = {
0442 .name = "usb_phy_gen_xceiv",
0443 .id = 0,
0444 };
0445
0446 static struct resource jz4740_udc_resources[] = {
0447 [0] = {
0448 .start = JZ4740_UDC_BASE_ADDR,
0449 .end = JZ4740_UDC_BASE_ADDR + 0x10000 - 1,
0450 .flags = IORESOURCE_MEM,
0451 },
0452 [1] = {
0453 .start = JZ4740_IRQ_UDC,
0454 .end = JZ4740_IRQ_UDC,
0455 .flags = IORESOURCE_IRQ,
0456 .name = "mc",
0457 },
0458 };
0459
0460 struct platform_device jz4740_udc_device = {
0461 .name = "musb-jz4740",
0462 .id = -1,
0463 .dev = {
0464 .dma_mask = &jz4740_udc_device.dev.coherent_dma_mask,
0465 .coherent_dma_mask = DMA_BIT_MASK(32),
0466 },
0467 .num_resources = ARRAY_SIZE(jz4740_udc_resources),
0468 .resource = jz4740_udc_resources,
0469 };
0470
0471 The ``jz4740_udc_xceiv_device`` platform device structure (line 2)
0472 describes the UDC transceiver with a name and id number.
0473
0474 At the time of this writing, note that ``usb_phy_gen_xceiv`` is the
0475 specific name to be used for all transceivers that are either built-in
0476 with reference USB IP or autonomous and doesn't require any PHY
0477 programming. You will need to set ``CONFIG_NOP_USB_XCEIV=y`` in the
0478 kernel configuration to make use of the corresponding transceiver
0479 driver. The id field could be set to -1 (equivalent to
0480 ``PLATFORM_DEVID_NONE``), -2 (equivalent to ``PLATFORM_DEVID_AUTO``) or
0481 start with 0 for the first device of this kind if we want a specific id
0482 number.
0483
0484 The ``jz4740_udc_resources`` resource structure (line 7) defines the UDC
0485 registers base addresses.
0486
0487 The first array (line 9 to 11) defines the UDC registers base memory
0488 addresses: start points to the first register memory address, end points
0489 to the last register memory address and the flags member defines the
0490 type of resource we are dealing with. So ``IORESOURCE_MEM`` is used to
0491 define the registers memory addresses. The second array (line 14 to 17)
0492 defines the UDC IRQ registers addresses. Since there is only one IRQ
0493 register available for the JZ4740 UDC, start and end point at the same
0494 address. The ``IORESOURCE_IRQ`` flag tells that we are dealing with IRQ
0495 resources, and the name ``mc`` is in fact hard-coded in the MUSB core in
0496 order for the controller driver to retrieve this IRQ resource by
0497 querying it by its name.
0498
0499 Finally, the ``jz4740_udc_device`` platform device structure (line 21)
0500 describes the UDC itself.
0501
0502 The ``musb-jz4740`` name (line 22) defines the MUSB driver that is used
0503 for this device; remember this is in fact the name that we used in the
0504 ``jz4740_driver`` platform driver structure in :ref:`musb-basics`.
0505 The id field (line 23) is set to -1 (equivalent to ``PLATFORM_DEVID_NONE``)
0506 since we do not need an id for the device: the MUSB controller driver was
0507 already set to allocate an automatic id in :ref:`musb-basics`. In the dev field
0508 we care for DMA related information here. The ``dma_mask`` field (line 25)
0509 defines the width of the DMA mask that is going to be used, and
0510 ``coherent_dma_mask`` (line 26) has the same purpose but for the
0511 ``alloc_coherent`` DMA mappings: in both cases we are using a 32 bits mask.
0512 Then the resource field (line 29) is simply a pointer to the resource
0513 structure defined before, while the ``num_resources`` field (line 28) keeps
0514 track of the number of arrays defined in the resource structure (in this
0515 case there were two resource arrays defined before).
0516
0517 With this quick overview of the UDC platform data at the ``arch/`` level now
0518 done, let's get back to the MUSB glue layer specific platform data in
0519 ``drivers/usb/musb/jz4740.c``:
0520
0521 .. code-block:: c
0522 :emphasize-lines: 3,5,7-9,11
0523
0524 static struct musb_hdrc_config jz4740_musb_config = {
0525 /* Silicon does not implement USB OTG. */
0526 .multipoint = 0,
0527 /* Max EPs scanned, driver will decide which EP can be used. */
0528 .num_eps = 4,
0529 /* RAMbits needed to configure EPs from table */
0530 .ram_bits = 9,
0531 .fifo_cfg = jz4740_musb_fifo_cfg,
0532 .fifo_cfg_size = ARRAY_SIZE(jz4740_musb_fifo_cfg),
0533 };
0534
0535 static struct musb_hdrc_platform_data jz4740_musb_platform_data = {
0536 .mode = MUSB_PERIPHERAL,
0537 .config = &jz4740_musb_config,
0538 };
0539
0540 First the glue layer configures some aspects of the controller driver
0541 operation related to the controller hardware specifics. This is done
0542 through the ``jz4740_musb_config`` :c:type:`musb_hdrc_config` structure.
0543
0544 Defining the OTG capability of the controller hardware, the multipoint
0545 member (line 3) is set to 0 (equivalent to false) since the JZ4740 UDC
0546 is not OTG compatible. Then ``num_eps`` (line 5) defines the number of USB
0547 endpoints of the controller hardware, including endpoint 0: here we have
0548 3 endpoints + endpoint 0. Next is ``ram_bits`` (line 7) which is the width
0549 of the RAM address bus for the MUSB controller hardware. This
0550 information is needed when the controller driver cannot automatically
0551 configure endpoints by reading the relevant controller hardware
0552 registers. This issue will be discussed when we get to device quirks in
0553 :ref:`musb-dev-quirks`. Last two fields (line 8 and 9) are also
0554 about device quirks: ``fifo_cfg`` points to the USB endpoints configuration
0555 table and ``fifo_cfg_size`` keeps track of the size of the number of
0556 entries in that configuration table. More on that later in
0557 :ref:`musb-dev-quirks`.
0558
0559 Then this configuration is embedded inside ``jz4740_musb_platform_data``
0560 :c:type:`musb_hdrc_platform_data` structure (line 11): config is a pointer to
0561 the configuration structure itself, and mode tells the controller driver
0562 if the controller hardware may be used as ``MUSB_HOST`` only,
0563 ``MUSB_PERIPHERAL`` only or ``MUSB_OTG`` which is a dual mode.
0564
0565 Remember that ``jz4740_musb_platform_data`` is then used to convey
0566 platform data information as we have seen in the probe function in
0567 :ref:`musb-basics`.
0568
0569 .. _musb-dev-quirks:
0570
0571 Device Quirks
0572 =============
0573
0574 Completing the platform data specific to your device, you may also need
0575 to write some code in the glue layer to work around some device specific
0576 limitations. These quirks may be due to some hardware bugs, or simply be
0577 the result of an incomplete implementation of the USB On-the-Go
0578 specification.
0579
0580 The JZ4740 UDC exhibits such quirks, some of which we will discuss here
0581 for the sake of insight even though these might not be found in the
0582 controller hardware you are working on.
0583
0584 Let's get back to the init function first:
0585
0586 .. code-block:: c
0587 :emphasize-lines: 12
0588
0589 static int jz4740_musb_init(struct musb *musb)
0590 {
0591 musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2);
0592 if (!musb->xceiv) {
0593 pr_err("HS UDC: no transceiver configured\n");
0594 return -ENODEV;
0595 }
0596
0597 /* Silicon does not implement ConfigData register.
0598 * Set dyn_fifo to avoid reading EP config from hardware.
0599 */
0600 musb->dyn_fifo = true;
0601
0602 musb->isr = jz4740_musb_interrupt;
0603
0604 return 0;
0605 }
0606
0607 Instruction on line 12 helps the MUSB controller driver to work around
0608 the fact that the controller hardware is missing registers that are used
0609 for USB endpoints configuration.
0610
0611 Without these registers, the controller driver is unable to read the
0612 endpoints configuration from the hardware, so we use line 12 instruction
0613 to bypass reading the configuration from silicon, and rely on a
0614 hard-coded table that describes the endpoints configuration instead::
0615
0616 static struct musb_fifo_cfg jz4740_musb_fifo_cfg[] = {
0617 { .hw_ep_num = 1, .style = FIFO_TX, .maxpacket = 512, },
0618 { .hw_ep_num = 1, .style = FIFO_RX, .maxpacket = 512, },
0619 { .hw_ep_num = 2, .style = FIFO_TX, .maxpacket = 64, },
0620 };
0621
0622 Looking at the configuration table above, we see that each endpoints is
0623 described by three fields: ``hw_ep_num`` is the endpoint number, style is
0624 its direction (either ``FIFO_TX`` for the controller driver to send packets
0625 in the controller hardware, or ``FIFO_RX`` to receive packets from
0626 hardware), and maxpacket defines the maximum size of each data packet
0627 that can be transmitted over that endpoint. Reading from the table, the
0628 controller driver knows that endpoint 1 can be used to send and receive
0629 USB data packets of 512 bytes at once (this is in fact a bulk in/out
0630 endpoint), and endpoint 2 can be used to send data packets of 64 bytes
0631 at once (this is in fact an interrupt endpoint).
0632
0633 Note that there is no information about endpoint 0 here: that one is
0634 implemented by default in every silicon design, with a predefined
0635 configuration according to the USB specification. For more examples of
0636 endpoint configuration tables, see ``musb_core.c``.
0637
0638 Let's now get back to the interrupt handler function:
0639
0640 .. code-block:: c
0641 :emphasize-lines: 18-19
0642
0643 static irqreturn_t jz4740_musb_interrupt(int irq, void *__hci)
0644 {
0645 unsigned long flags;
0646 irqreturn_t retval = IRQ_NONE;
0647 struct musb *musb = __hci;
0648
0649 spin_lock_irqsave(&musb->lock, flags);
0650
0651 musb->int_usb = musb_readb(musb->mregs, MUSB_INTRUSB);
0652 musb->int_tx = musb_readw(musb->mregs, MUSB_INTRTX);
0653 musb->int_rx = musb_readw(musb->mregs, MUSB_INTRRX);
0654
0655 /*
0656 * The controller is gadget only, the state of the host mode IRQ bits is
0657 * undefined. Mask them to make sure that the musb driver core will
0658 * never see them set
0659 */
0660 musb->int_usb &= MUSB_INTR_SUSPEND | MUSB_INTR_RESUME |
0661 MUSB_INTR_RESET | MUSB_INTR_SOF;
0662
0663 if (musb->int_usb || musb->int_tx || musb->int_rx)
0664 retval = musb_interrupt(musb);
0665
0666 spin_unlock_irqrestore(&musb->lock, flags);
0667
0668 return retval;
0669 }
0670
0671 Instruction on line 18 above is a way for the controller driver to work
0672 around the fact that some interrupt bits used for USB host mode
0673 operation are missing in the ``MUSB_INTRUSB`` register, thus left in an
0674 undefined hardware state, since this MUSB controller hardware is used in
0675 peripheral mode only. As a consequence, the glue layer masks these
0676 missing bits out to avoid parasite interrupts by doing a logical AND
0677 operation between the value read from ``MUSB_INTRUSB`` and the bits that
0678 are actually implemented in the register.
0679
0680 These are only a couple of the quirks found in the JZ4740 USB device
0681 controller. Some others were directly addressed in the MUSB core since
0682 the fixes were generic enough to provide a better handling of the issues
0683 for others controller hardware eventually.
0684
0685 Conclusion
0686 ==========
0687
0688 Writing a Linux MUSB glue layer should be a more accessible task, as
0689 this documentation tries to show the ins and outs of this exercise.
0690
0691 The JZ4740 USB device controller being fairly simple, I hope its glue
0692 layer serves as a good example for the curious mind. Used with the
0693 current MUSB glue layers, this documentation should provide enough
0694 guidance to get started; should anything gets out of hand, the linux-usb
0695 mailing list archive is another helpful resource to browse through.
0696
0697 Acknowledgements
0698 ================
0699
0700 Many thanks to Lars-Peter Clausen and Maarten ter Huurne for answering
0701 my questions while I was writing the JZ4740 glue layer and for helping
0702 me out getting the code in good shape.
0703
0704 I would also like to thank the Qi-Hardware community at large for its
0705 cheerful guidance and support.
0706
0707 Resources
0708 =========
0709
0710 USB Home Page: https://www.usb.org
0711
0712 linux-usb Mailing List Archives: https://marc.info/?l=linux-usb
0713
0714 USB On-the-Go Basics:
0715 https://www.maximintegrated.com/app-notes/index.mvp/id/1822
0716
0717 :ref:`Writing USB Device Drivers <writing-usb-driver>`
0718
0719 Texas Instruments USB Configuration Wiki Page:
0720 http://processors.wiki.ti.com/index.php/Usbgeneralpage