1<html><head><meta http-equiv="Content-Type" content="text/html; charset=ANSI_X3.4-1968"><title>Chapter 3. Handling IRQs</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="linux-musb-basics.html" title="Chapter 2. Linux MUSB Basics"><link rel="next" href="device-platform-data.html" title="Chapter 4. Device Platform Data"></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 3. Handling IRQs</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="linux-musb-basics.html">Prev</a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <a accesskey="n" href="device-platform-data.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="handling-irqs"></a>Chapter 3. Handling IRQs</h1></div></div></div><p> 2 Additionally to the MUSB controller hardware basic setup and 3 registration, the glue layer is also responsible for handling the 4 IRQs: 5 </p><pre class="programlisting"> 6static irqreturn_t jz4740_musb_interrupt(int irq, void *__hci) 7{ 8 unsigned long flags; 9 irqreturn_t retval = IRQ_NONE; 10 struct musb *musb = __hci; 11 12 spin_lock_irqsave(&musb->lock, flags); 13 14 musb->int_usb = musb_readb(musb->mregs, MUSB_INTRUSB); 15 musb->int_tx = musb_readw(musb->mregs, MUSB_INTRTX); 16 musb->int_rx = musb_readw(musb->mregs, MUSB_INTRRX); 17 18 /* 19 * The controller is gadget only, the state of the host mode IRQ bits is 20 * undefined. Mask them to make sure that the musb driver core will 21 * never see them set 22 */ 23 musb->int_usb &= MUSB_INTR_SUSPEND | MUSB_INTR_RESUME | 24 MUSB_INTR_RESET | MUSB_INTR_SOF; 25 26 if (musb->int_usb || musb->int_tx || musb->int_rx) 27 retval = musb_interrupt(musb); 28 29 spin_unlock_irqrestore(&musb->lock, flags); 30 31 return retval; 32} 33 </pre><p> 34 Here the glue layer mostly has to read the relevant hardware 35 registers and pass their values on to the controller driver which 36 will handle the actual event that triggered the IRQ. 37 </p><p> 38 The interrupt handler critical section is protected by the 39 spin_lock_irqsave() and counterpart spin_unlock_irqrestore() 40 functions (line 7 and 24 respectively), which prevent the 41 interrupt handler code to be run by two different threads at the 42 same time. 43 </p><p> 44 Then the relevant interrupt registers are read (line 9 to 11): 45 </p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p> 46 MUSB_INTRUSB: indicates which USB interrupts are currently 47 active, 48 </p></li><li class="listitem"><p> 49 MUSB_INTRTX: indicates which of the interrupts for TX 50 endpoints are currently active, 51 </p></li><li class="listitem"><p> 52 MUSB_INTRRX: indicates which of the interrupts for TX 53 endpoints are currently active. 54 </p></li></ul></div><p> 55 Note that musb_readb() is used to read 8-bit registers at most, 56 while musb_readw() allows us to read at most 16-bit registers. 57 There are other functions that can be used depending on the size 58 of your device registers. See musb_io.h for more information. 59 </p><p> 60 Instruction on line 18 is another quirk specific to the JZ4740 61 USB device controller, which will be discussed later in <a class="link" href="device-quirks.html" title="Chapter 5. Device Quirks">Chapter 5</a>. 62 </p><p> 63 The glue layer still needs to register the IRQ handler though. 64 Remember the instruction on line 14 of the init function: 65 </p><pre class="programlisting"> 66static int jz4740_musb_init(struct musb *musb) 67{ 68 musb->isr = jz4740_musb_interrupt; 69 70 return 0; 71} 72 </pre><p> 73 This instruction sets a pointer to the glue layer IRQ handler 74 function, in order for the controller hardware to call the handler 75 back when an IRQ comes from the controller hardware. The interrupt 76 handler is now implemented and registered. 77 </p></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="linux-musb-basics.html">Prev</a> </td><td width="20%" align="center"> </td><td width="40%" align="right"> <a accesskey="n" href="device-platform-data.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">Chapter 2. Linux MUSB Basics </td><td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td><td width="40%" align="right" valign="top"> Chapter 4. Device Platform Data</td></tr></table></div></body></html> 78