⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pxa_ir.c

📁 优龙2410linux2.6.8内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* *  linux/drivers/net/irda/pxa_ir.c * *  Author: *  Alexey Lugovskoy RTSoft.  *	lugovskoy@rtsoft.msk.ru * *  Dmitrij Frasenyak RTSoft.  *      sed@mipt.sw.ru * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * *  Infra-red SIR and FIR driver for the PXA 210/250 embedded microprocessors *  Based on linux/drivers/net/irda/sa1100_ir.c * */#include <linux/config.h>#include <linux/module.h>#include <linux/types.h>#include <linux/init.h>#include <linux/errno.h>#include <linux/netdevice.h>#include <linux/slab.h>#include <linux/rtnetlink.h>#include <linux/interrupt.h>#include <linux/delay.h>#include <linux/ioport.h>#include <linux/delay.h>#include <linux/dma-mapping.h>#include <linux/pm.h>#include <net/irda/irda.h>#include <net/irda/irmod.h>#include <net/irda/wrapper.h>#include <net/irda/irda_device.h>#include <asm/irq.h>#include <asm/dma.h>#include <asm/hardware.h>#include <asm/mach-types.h>#include <asm/arch/lubbock.h>static int rx_count = 0;static int tx_count = 0;/* * Our netdevice.  There is only ever one of these. */ static struct net_device *netdev;struct pxa250_irda {		unsigned char		open;	int			speed;	int			newspeed;	struct sk_buff		*txskb;	struct sk_buff		*rxskb;		/* => FIR */	unsigned int		fir_irq;	int			txdma_ch;	int			rxdma_ch;	dma_addr_t		txbuf_dma;	dma_addr_t		rxbuf_dma;	void* 			txbuf_dma_virt;	void* 			rxbuf_dma_virt;	/* <= FIR*/	struct net_device_stats	stats;	struct device		*dev;	struct irlap_cb		*irlap;	struct pm_dev		*pmdev;	struct qos_info		qos;	/* => SIR */	iobuff_t		tx_buff;	iobuff_t		rx_buff;	/* <= SIR */};#define IS_FIR(si)		((si)->speed >= 4000000)#define HPSIR_MAX_RXLEN		2050#define HPSIR_MAX_TXLEN		2050#define TXBUFF_MAX_SIZE		HPSIR_MAX_TXLEN#define SET_SIR_MODE            STISR = STISR_RCVEIR | STISR_XMITIR | STISR_XMODE/* * If you want to disable debug information * please uncomment line bellow */#define PXA_FIR_DUMP_ENABLE#undef PXA_FIR_DUMP_ENABLE     #define PXA_FIR_DEBUG_ENABLE#undef PXA_FIR_DEBUG_ENABLE              #define PXA_FIR_IRQ_DEBUG_ENABLE#undef PXA_FIR_IRQ_DEBUG_ENABLE               #ifdef PXA_FIR_DEBUG_ENABLE#define __ECHO_IN printk(KERN_ERR "%s: enter\n",__FUNCTION__);#define __ECHO_OUT printk(KERN_ERR "%s: exit\n",__FUNCTION__);#define DBG(args...) printk(KERN_ERR __FUNCTION__"():"args);#else#define __ECHO_IN#define __ECHO_OUT#define DBG(args...)#endif#ifdef PXA_FIR_IRQ_DEBUG_ENABLE#define DBG_IRQ(args...) printk(KERN_ERR __FUNCTION__"():"args);#else#define DBG_IRQ(args...)#endifstatic int pxa250_irda_set_speed(struct net_device *dev,int speed);static void pxa250_start_rx_dma(struct net_device *dev);/************************************************************************** *			Misc FIR/SIR functions				  * **************************************************************************//* * Allocate the receive buffer, unless it is already allocated. */static int pxa250_irda_rx_alloc(struct pxa250_irda *si){   __ECHO_IN;      if (si->rxskb)      return 0;   si->rxskb = alloc_skb(HPSIR_MAX_RXLEN + 1, GFP_ATOMIC);   if (!si->rxskb) {      printk(KERN_ERR "pxa250_ir: out of memory for RX SKB\n");      return -ENOMEM;   }   /*    * Align any IP headers that may be contained    * within the frame.    */   skb_reserve(si->rxskb, 1);   __ECHO_OUT;   return 0;}/************************************************************************** *			FIR						  * **************************************************************************/static inline void pxa250_dma_stop(int ch){   __ECHO_IN;   DCSR(ch) &= ~DCSR_RUN;   __ECHO_OUT;   }static void pxa250_ficp_rx_start(void){   ICCR0 = 0;   ICCR2 =  1 << 2 | 0 << 3 ;    ICCR0 = ICCR0_ITR ;   ICCR0 |= ICCR0_RIE |  ICCR0_RXE ; }/* * Change Alternative Function encoding * Enable ICP unit * Disabe STUART unit * Enable IRQ unit clock; * Configure direction of GPIO used by ICP */static void pxa250_do_fir_GPIO_config(void){   /*    * Modify GPIO 46 and 47 Alternate Function     */   __ECHO_IN;   /*Switch AF*/   pxa_gpio_mode (GPIO46_ICPRXD_MD);   pxa_gpio_mode (GPIO47_ICPTXD_MD);#ifndef CONFIG_ARCH_FS_PXA255	//we don't remap FPGA, so can't do this,hzh   if (machine_is_lubbock())      LUB_MISC_WR |= 1 << 4;#endif   /*init clock*/   CKEN |= CKEN13_FICP;   __ECHO_OUT;}/* * Low level hardware configuration and startup. */static int pxa250_fir_irda_startup(struct pxa250_irda *si){	__ECHO_IN;	/*	 * Disable STUART	 */	STIER &= ~IER_UUE;	/*Disable STUART FIFO */	STFCR = 0;	/*	 * Do low level configuration for HW AF and clock	 */	pxa250_do_fir_GPIO_config();	__ECHO_OUT;	return 0;}/* * Aieeeeee .. we should never get here :( */static void pxa250_irda_rxdma_irq(int ch,void *id, struct pt_regs *regs){   struct net_device *dev=id;   struct pxa250_irda *si=dev->priv;   u_int dcsr;   __ECHO_IN;   /*     * Make sure that irq is our.    */   if ( ch != si->rxdma_ch )      /*just*/ return;   /*    * Check status     */   dcsr = DCSR(ch);   DBG("DCSR=%x\n",dcsr);   if (dcsr &  DCSR_STOPSTATE )   {      DBG_IRQ("Chanel %d in stop state\n",ch);   }   if (dcsr &  DCSR_BUSERR )   {      /*       * BUS Error we must restart reception       */            DBG("PXA IrDA: bus error interrupt on channel %d\n", ch);      DCSR(ch) |= DCSR_BUSERR;   }   if (dcsr &  DCSR_ENDINTR )   {      DBG("PXA IrDA: Normal end of dma channel %d - packet to big\n", ch);      DCSR(ch) |= DCSR_ENDINTR;   }   /* no mater what restart rx*/   pxa250_start_rx_dma(dev);      return ;   }static void pxa250_irda_txdma_irq(int ch, void *id , struct pt_regs *regs){   struct net_device *dev=id;   struct pxa250_irda *si=dev->priv;   struct sk_buff *skb = si->txskb;   u_int dcsr;   __ECHO_IN;   DBG_IRQ("transmit\n");            /*     * Make sure that irq is our.    */   if ( ch != si->txdma_ch )      /*just*/ return;   /*    * Check status     */   dcsr = DCSR(ch);   DBG("DCSR=%x",dcsr);   if (dcsr &  DCSR_STOPSTATE )   {      DBG("Chanel %d in stop state\n",ch);   }   if (dcsr &  DCSR_BUSERR )   {      DBG("PXA IrDA: bus error interrupt on channel %d\n", ch);      DCSR(ch) |= DCSR_BUSERR;      si->txskb = NULL;   }   if (dcsr &  DCSR_ENDINTR )   {      DBG("PXA IrDA: Normal end of dma channel %d\n", ch);      DCSR(ch) |= DCSR_ENDINTR;      si->txskb = NULL;   }   /*    * Account and free the packet.    */   if (skb)   {      si->stats.tx_packets ++;      si->stats.tx_bytes += skb->len;      dev_kfree_skb_irq(skb);   }	/*Disable transceiver and enable receiver*/	if (si->newspeed) {	   pxa250_irda_set_speed(dev, si->newspeed);	   si->newspeed = 0;	}	while (ICSR1 & ICSR1_TBY)	   udelay(1);	     	ICCR0 &= ~ICCR0_TXE;		enable_irq(si->fir_irq);  	ICCR0 |= ICCR0_RXE; 	/*	 * Make sure that the TX queue is available for sending	 * (for retries).  TX has priority over RX at all times.	 */	netif_wake_queue(dev);		__ECHO_OUT;}static void pxa250_start_rx_dma(struct net_device *dev){   struct pxa250_irda *si = dev->priv;   int ch=si->rxdma_ch;   if (!si->rxskb) {      DBG("rx buffer went missing\n");/*        return; */   }   DCSR(ch)=0;   DCSR(ch)=DCSR_NODESC;   DSADR(ch) = __PREG(ICDR);   DTADR(ch) = si->rxbuf_dma; /* phisical address */;   /* We should never do END_IRQ.  !!!*/   DCMD(ch) = DCMD_ENDIRQEN| DCMD_INCTRGADDR | DCMD_FLOWSRC | DCMD_BURST8 | DCMD_WIDTH1 | HPSIR_MAX_RXLEN;   /*    * All right information will be available as soon as we set RXE flag    */      DCSR(ch) = DCSR_ENDINTR | DCSR_BUSERR;   DCSR(ch) = DCSR_RUN | DCSR_NODESC ;}static int pxa250_get_rx_len(struct pxa250_irda *si){   /*    * DMA have to be stoped here    */   if ( ! (DCSR(si->rxdma_ch) & DCSR_STOPSTATE) )      printk("warning dma have to be stoped befor counting len\n");      return ( HPSIR_MAX_RXLEN - ( DCMD(si->rxdma_ch) & DCMD_LENGTH ) );   }static void pxa250_irda_fir_error(struct net_device *dev){   struct pxa250_irda *si = dev->priv;   struct sk_buff *skb = si->rxskb;   int len;   int stat,data;   __ECHO_IN;         if (!skb)      {	 printk("pxa250 fir_error: SKB is NULL!\n");	 return;      }      /*       * Get the current data position.       */      len=pxa250_get_rx_len(si);      DBG("RXLEN=%d\n",len);      memcpy(skb->data, si->rxbuf_dma_virt, len);      do {	 /*	  * Read Status, and then Data.	  */	   stat = ICSR1;	   rmb();	   data = ICDR;	   if (stat & (ICSR1_CRE | ICSR1_ROR)) {	      si->stats.rx_errors++;	      if (stat & ICSR1_CRE)		 si->stats.rx_crc_errors++;	      if (stat & ICSR1_ROR)		 si->stats.rx_frame_errors++;	   } else	      skb->data[len++] = data;		/*		 * If we hit the end of frame, there's		 * no point in continuing.		 */	   if (stat & ICSR1_EOF)	      break;	} while (ICSR0 & ICSR0_EIF);	if (stat & ICSR1_EOF) {	   si->rxskb = NULL;	   skb_put(skb, len);	   skb->dev = dev;	   skb->mac.raw = skb->data;	   skb->protocol = htons(ETH_P_IRDA);	   si->stats.rx_packets++;	   si->stats.rx_bytes += len;	   /*	    * Before we pass the buffer up, allocate a new one.	    */	   si->rxskb = alloc_skb(HPSIR_MAX_RXLEN + 1, GFP_ATOMIC);	   if (!si->rxskb) {	      printk(KERN_ERR "pxa250_ir: out of memory for RX SKB\n");	      return;	   }	   /*	    * Align any IP headers that may be contained	    * within the frame.	    */	   skb_reserve(si->rxskb, 1);	   netif_rx(skb);	}}/* * FIR format interrupt service routine.  We only have to * handle RX events; transmit events go via the TX DMA irq handler. * * No matter what, we disable RX, process, and then restart RX. */static irqreturn_t pxa250_irda_fir_irq(int irq, void *dev_id, struct pt_regs *regs){   struct net_device *dev = dev_id;   struct pxa250_irda *si = dev->priv;   int status;      /*    * Stop RX    */   __ECHO_IN;   pxa250_dma_stop(si->rxdma_ch);      /*    * Framing error - we throw away the packet completely.    * Clearing RXE flushes the error conditions and data    * from the fifo.    */   status=ICSR0;   

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -