/* FIR Transmit DMA interrupt handler */ static void pxa_irda_fir_dma_tx_irq(int channel, void *data) { struct net_device *dev = data; struct pxa_irda *si = netdev_priv(dev); int dcsr; dcsr = DCSR(channel); DCSR(channel) = dcsr & ~DCSR_RUN; if (dcsr & DCSR_ENDINTR) { si->stats.tx_packets++; si->stats.tx_bytes += si->dma_tx_buff_len; } else { si->stats.tx_errors++; } while (ICSR1 & ICSR1_TBY) cpu_relax(); si->last_oscr = OSCR; /* * HACK: It looks like the TBY bit is dropped too soon. * Without this delay things break. */ udelay(120); if (si->newspeed) { pxa_irda_set_speed(si, si->newspeed); si->newspeed = 0; } else { int i = 64; ICCR0 = 0; pxa_irda_fir_dma_rx_start(si); while ((ICSR1 & ICSR1_RNE) && i--) (void)ICDR; ICCR0 = ICCR0_ITR | ICCR0_RXE; if (i < 0) printk(KERN_ERR "pxa_ir: cannot clear Rx FIFO!\n"); } netif_wake_queue(dev); }
/* FIR interrupt handler */ static irqreturn_t pxa_irda_fir_irq(int irq, void *dev_id) { struct net_device *dev = dev_id; struct pxa_irda *si = netdev_priv(dev); int icsr0, i = 64; /* stop RX DMA */ DCSR(si->rxdma) &= ~DCSR_RUN; si->last_oscr = OSCR; icsr0 = ICSR0; if (icsr0 & (ICSR0_FRE | ICSR0_RAB)) { if (icsr0 & ICSR0_FRE) { printk(KERN_DEBUG "pxa_ir: fir receive frame error\n"); si->stats.rx_frame_errors++; } else { printk(KERN_DEBUG "pxa_ir: fir receive abort\n"); si->stats.rx_errors++; } ICSR0 = icsr0 & (ICSR0_FRE | ICSR0_RAB); } if (icsr0 & ICSR0_EIF) { /* An error in FIFO occured, or there is a end of frame */ pxa_irda_fir_irq_eif(si, dev, icsr0); } ICCR0 = 0; pxa_irda_fir_dma_rx_start(si); while ((ICSR1 & ICSR1_RNE) && i--) (void)ICDR; ICCR0 = ICCR0_ITR | ICCR0_RXE; if (i < 0) printk(KERN_ERR "pxa_ir: cannot clear Rx FIFO!\n"); return IRQ_HANDLED; }
/* * Set the IrDA communications speed. */ static int pxa_irda_set_speed(struct pxa_irda *si, int speed) { unsigned long flags; unsigned int divisor; switch (speed) { case 9600: case 19200: case 38400: case 57600: case 115200: /* refer to PXA250/210 Developer's Manual 10-7 */ /* BaudRate = 14.7456 MHz / (16*Divisor) */ divisor = 14745600 / (16 * speed); local_irq_save(flags); if (IS_FIR(si)) { /* stop RX DMA */ DCSR(si->rxdma) &= ~DCSR_RUN; /* disable FICP */ ICCR0 = 0; pxa_irda_disable_clk(si); /* set board transceiver to SIR mode */ si->pdata->transceiver_mode(si->dev, IR_SIRMODE); /* enable the STUART clock */ pxa_irda_enable_sirclk(si); } /* disable STUART first */ STIER = 0; /* access DLL & DLH */ STLCR |= LCR_DLAB; STDLL = divisor & 0xff; STDLH = divisor >> 8; STLCR &= ~LCR_DLAB; si->speed = speed; STISR = IrSR_IR_RECEIVE_ON | IrSR_XMODE_PULSE_1_6; STIER = IER_UUE | IER_RLSE | IER_RAVIE | IER_RTIOE; local_irq_restore(flags); break; case 4000000: local_irq_save(flags); /* disable STUART */ STIER = 0; STISR = 0; pxa_irda_disable_clk(si); /* disable FICP first */ ICCR0 = 0; /* set board transceiver to FIR mode */ si->pdata->transceiver_mode(si->dev, IR_FIRMODE); /* enable the FICP clock */ pxa_irda_enable_firclk(si); si->speed = speed; pxa_irda_fir_dma_rx_start(si); ICCR0 = ICCR0_ITR | ICCR0_RXE; local_irq_restore(flags); break; default: return -EINVAL; } return 0; }
static int pxa_irda_set_speed(struct pxa_irda *si, int speed) { unsigned long flags; unsigned int divisor; switch (speed) { case 9600: case 19200: case 38400: case 57600: case 115200: divisor = 14745600 / (16 * speed); local_irq_save(flags); if (IS_FIR(si)) { DCSR(si->rxdma) &= ~DCSR_RUN; ICCR0 = 0; pxa_irda_disable_clk(si); pxa_irda_set_mode(si, IR_SIRMODE); pxa_irda_enable_sirclk(si); } STIER = 0; STLCR |= LCR_DLAB; STDLL = divisor & 0xff; STDLH = divisor >> 8; STLCR &= ~LCR_DLAB; si->speed = speed; STISR = IrSR_IR_RECEIVE_ON | IrSR_XMODE_PULSE_1_6; STIER = IER_UUE | IER_RLSE | IER_RAVIE | IER_RTIOE; local_irq_restore(flags); break; case 4000000: local_irq_save(flags); STIER = 0; STISR = 0; pxa_irda_disable_clk(si); ICCR0 = 0; pxa_irda_set_mode(si, IR_FIRMODE); pxa_irda_enable_firclk(si); si->speed = speed; pxa_irda_fir_dma_rx_start(si); ICCR0 = ICCR0_ITR | ICCR0_RXE; local_irq_restore(flags); break; default: return -EINVAL; } return 0; }