1<html><head><meta http-equiv="Content-Type" content="text/html; charset=ANSI_X3.4-1968"><title>Chapter 5. Device Quirks</title><meta name="generator" content="DocBook XSL Stylesheets V1.78.1"><link rel="home" href="index.html" title="Writing an MUSB Glue Layer"><link rel="up" href="index.html" title="Writing an MUSB Glue Layer"><link rel="prev" href="device-platform-data.html" title="Chapter 4. Device Platform Data"><link rel="next" href="conclusion.html" title="Chapter 6. Conclusion"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">Chapter 5. Device Quirks</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="device-platform-data.html">Prev</a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <a accesskey="n" href="conclusion.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="device-quirks"></a>Chapter 5. Device Quirks</h1></div></div></div><p> 2 Completing the platform data specific to your device, you may also 3 need to write some code in the glue layer to work around some 4 device specific limitations. These quirks may be due to some 5 hardware bugs, or simply be the result of an incomplete 6 implementation of the USB On-the-Go specification. 7 </p><p> 8 The JZ4740 UDC exhibits such quirks, some of which we will discuss 9 here for the sake of insight even though these might not be found 10 in the controller hardware you are working on. 11 </p><p> 12 Let's get back to the init function first: 13 </p><pre class="programlisting"> 14static int jz4740_musb_init(struct musb *musb) 15{ 16 musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2); 17 if (!musb->xceiv) { 18 pr_err("HS UDC: no transceiver configured\n"); 19 return -ENODEV; 20 } 21 22 /* Silicon does not implement ConfigData register. 23 * Set dyn_fifo to avoid reading EP config from hardware. 24 */ 25 musb->dyn_fifo = true; 26 27 musb->isr = jz4740_musb_interrupt; 28 29 return 0; 30} 31 </pre><p> 32 Instruction on line 12 helps the MUSB controller driver to work 33 around the fact that the controller hardware is missing registers 34 that are used for USB endpoints configuration. 35 </p><p> 36 Without these registers, the controller driver is unable to read 37 the endpoints configuration from the hardware, so we use line 12 38 instruction to bypass reading the configuration from silicon, and 39 rely on a hard-coded table that describes the endpoints 40 configuration instead: 41 </p><pre class="programlisting"> 42static struct musb_fifo_cfg jz4740_musb_fifo_cfg[] = { 43{ .hw_ep_num = 1, .style = FIFO_TX, .maxpacket = 512, }, 44{ .hw_ep_num = 1, .style = FIFO_RX, .maxpacket = 512, }, 45{ .hw_ep_num = 2, .style = FIFO_TX, .maxpacket = 64, }, 46}; 47 </pre><p> 48 Looking at the configuration table above, we see that each 49 endpoints is described by three fields: hw_ep_num is the endpoint 50 number, style is its direction (either FIFO_TX for the controller 51 driver to send packets in the controller hardware, or FIFO_RX to 52 receive packets from hardware), and maxpacket defines the maximum 53 size of each data packet that can be transmitted over that 54 endpoint. Reading from the table, the controller driver knows that 55 endpoint 1 can be used to send and receive USB data packets of 512 56 bytes at once (this is in fact a bulk in/out endpoint), and 57 endpoint 2 can be used to send data packets of 64 bytes at once 58 (this is in fact an interrupt endpoint). 59 </p><p> 60 Note that there is no information about endpoint 0 here: that one 61 is implemented by default in every silicon design, with a 62 predefined configuration according to the USB specification. For 63 more examples of endpoint configuration tables, see musb_core.c. 64 </p><p> 65 Let's now get back to the interrupt handler function: 66 </p><pre class="programlisting"> 67static irqreturn_t jz4740_musb_interrupt(int irq, void *__hci) 68{ 69 unsigned long flags; 70 irqreturn_t retval = IRQ_NONE; 71 struct musb *musb = __hci; 72 73 spin_lock_irqsave(&musb->lock, flags); 74 75 musb->int_usb = musb_readb(musb->mregs, MUSB_INTRUSB); 76 musb->int_tx = musb_readw(musb->mregs, MUSB_INTRTX); 77 musb->int_rx = musb_readw(musb->mregs, MUSB_INTRRX); 78 79 /* 80 * The controller is gadget only, the state of the host mode IRQ bits is 81 * undefined. Mask them to make sure that the musb driver core will 82 * never see them set 83 */ 84 musb->int_usb &= MUSB_INTR_SUSPEND | MUSB_INTR_RESUME | 85 MUSB_INTR_RESET | MUSB_INTR_SOF; 86 87 if (musb->int_usb || musb->int_tx || musb->int_rx) 88 retval = musb_interrupt(musb); 89 90 spin_unlock_irqrestore(&musb->lock, flags); 91 92 return retval; 93} 94 </pre><p> 95 Instruction on line 18 above is a way for the controller driver to 96 work around the fact that some interrupt bits used for USB host 97 mode operation are missing in the MUSB_INTRUSB register, thus left 98 in an undefined hardware state, since this MUSB controller 99 hardware is used in peripheral mode only. As a consequence, the 100 glue layer masks these missing bits out to avoid parasite 101 interrupts by doing a logical AND operation between the value read 102 from MUSB_INTRUSB and the bits that are actually implemented in 103 the register. 104 </p><p> 105 These are only a couple of the quirks found in the JZ4740 USB 106 device controller. Some others were directly addressed in the MUSB 107 core since the fixes were generic enough to provide a better 108 handling of the issues for others controller hardware eventually. 109 </p></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="device-platform-data.html">Prev</a> </td><td width="20%" align="center"> </td><td width="40%" align="right"> <a accesskey="n" href="conclusion.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">Chapter 4. Device Platform Data </td><td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td><td width="40%" align="right" valign="top"> Chapter 6. Conclusion</td></tr></table></div></body></html> 110