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

📄 omap24xx-ir.c

📁 Linux Kernel 2.6.9 for OMAP1710
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * BRIEF MODULE DESCRIPTION * *      Infra-red driver for the OMAP24XX Platform *          (SIR/MIR/FIR modes) *          (based on omap-sir.c) * * Copyright 2003 MontaVista Software Inc. * Author: MontaVista Software, Inc. *         source@mvista.com * * Copyright 2004 Texas Instruments. * *  This program is free software; you can redistribute  it and/or modify it *  under  the terms of  the GNU General  Public License as published by the *  Free Software Foundation;  either version 2 of the  License, or (at your *  option) any later version. * *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT, *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * *  You should have received a copy of the  GNU General Public License along *  with this program; if not, write  to the Free Software Foundation, Inc., *  675 Mass Ave, Cambridge, MA 02139, USA. * Modifications: Feb 2004, Texas Instruments - Ported to 2.6 kernel (Feb 2004). * Apr 2004, Texas Instruments - Added support for H3 (Apr 2004). * May 2004, Texas Instruments - Added support for H4 (May 2004). */#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/dma-mapping.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/io.h>#include <asm/hardware.h>#include <asm/serial.h>#include <asm/mach-types.h>#include <asm/dma.h>#include <asm/arch/gpio.h>#include <linux/i2c.h>#include <asm/arch/mux.h>#include "omap24xx-ir.h"#define SIR_MODE 0#define MIR_MODE 1#define FIR_MODE 2/* * Our netdevice.  There is only ever one of these. */unsigned long uart3_base;static struct net_device *netdev;	/* Our net device */static int rx_state = 0;	/* RX state for IOCTL */struct omap24xx_irda {	unsigned char open;	int speed;		/* Current IrDA speed */	int newspeed;	struct net_device_stats stats;	struct irlap_cb *irlap;	struct qos_info qos;	int rx_dma_channel;	int tx_dma_channel;	dma_addr_t rx_buf_dma_phys;	/* Physical adress of RX DMA buffer */	dma_addr_t tx_buf_dma_phys;	/* Physical adress of TX DMA buffer */	void *rx_buf_dma_virt;	/* Virtual adress of RX DMA buffer */	void *tx_buf_dma_virt;	/* Virtual adress of TX DMA buffer */	struct device *dev;};/* Functions to read and write to the I/O expanders */int read_gpio_expa(u8 * val, int addr);int write_gpio_expa(u8 val, int addr);/* * If you want to disable debug information * please uncomment line bellow *///#define OMAP24XX_IR_DEBUG_ENABLE #undef OMAP24XX_IR_DEBUG_ENABLE#ifdef  OMAP24XX_IR_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#define DBG_IRQ(args...) printk(KERN_ERR __FUNCTION__"():"args);/* forward declarations */#define BASE_CLK  48000000static int omap24xx_irda_set_speed(struct net_device *dev, int speed);static void omap24xx_irda_start_rx_dma(struct omap24xx_irda *si){	/* Configure DMA */	omap_set_dma_src_params(si->rx_dma_channel, 0x00, OMAP2420_UART3_BASE,				0, 0);	omap_set_dma_dest_params(si->rx_dma_channel, 0x01, si->rx_buf_dma_phys,				 0, 0);	omap_set_dma_transfer_params(si->rx_dma_channel, OMAP_DMA_DATA_TYPE_S8,				     4096, 1, 0x00, OMAP24XX_TRIGGER_RX, 0);	omap_start_dma(si->rx_dma_channel);}static void omap24xx_start_tx_dma(struct omap24xx_irda *si, int size){	omap_set_dma_dest_params(si->tx_dma_channel, 0x0, OMAP2420_UART3_BASE,				 0, 0);	omap_set_dma_src_params(si->tx_dma_channel, 0x01, si->tx_buf_dma_phys,				0, 0);	omap_set_dma_transfer_params(si->tx_dma_channel, OMAP_DMA_DATA_TYPE_S8,				     size, 1, 0x00, OMAP24XX_TRIGGER_TX, 0);	omap_start_dma(si->tx_dma_channel);}/* DMA RX callback - normally, we should not go here,   it calls only if something is going wrong */staticvoid omap24xx_irda_rx_dma_callback(int lch, u16 ch_status, void *data){	struct net_device *dev = data;	struct omap24xx_irda *si = dev->priv;	printk(KERN_ERR "RX Transfer error or very big frame \n");	/* Clear interrupts */	readb(UART3_IIR);	si->stats.rx_frame_errors++;	readb(UART3_RESUME);	/* Re-init RX DMA */	omap24xx_irda_start_rx_dma(si);}/* DMA TX callback - calling when frame transfer has been finished */staticvoid omap24xx_irda_tx_dma_callback(int lch, u16 ch_status, void *data){	struct net_device *dev = data;	struct omap24xx_irda *si = dev->priv;	/*Stop DMA controller */	omap_stop_dma(si->tx_dma_channel);}/* * Set the IrDA communications speed. * Interrupt have to be disabled here. */staticint omap24xx_irda_startup(struct net_device *dev){	__ECHO_IN;	writeb(0x07, UART3_MDR1);	/* Put UART3 in reset mode */	/* Clear DLH and DLL */	writeb(1 << 7, UART3_LCR);	writeb(0, UART3_DLL);	writeb(0, UART3_DLH);	writeb(0xbf, UART3_LCR);	writeb(1 << 4, UART3_EFR);	writeb(1 << 7, UART3_LCR);	/* Enable access to UART3_TLR and UART3_TCR registers */	writeb(1 << 6, UART3_MCR);	writeb(0, UART3_SCR);	/* Set Rx trigger to 1 and Tx trigger to 1 */	writeb(0, UART3_TLR);	/* Set LCR to 8 bits and 1 stop bit */	writeb(0x03, UART3_LCR);	/* Clear RX and TX FIFO and enable FIFO */	/* Use DMA Req for transfers */	writeb((1 << 2) | (1 << 1) | (1 << 3) | (1 << 4) | (1 << 6) | 1,	       UART3_FCR);	writeb(0, UART3_MCR);	writeb((1 << 7) | (1 << 6), UART3_SCR);	/* Enable UART3 SIR Mode,(Frame-length method to end frames) */	writeb(1, UART3_MDR1);	/* Set Status FIFO trig to 1 */	writeb(0, UART3_MDR2);	/* Enables RXIR input */	/* and disable TX underrun */	/* SEND_SIP pulse */	//   writeb((1 << 7) | (1 << 6) | (1 << 4), UART3_ACREG);	writeb((1 << 6) | (1 << 4), UART3_ACREG);	/* Enable EOF Interrupt only */	writeb((1 << 7) | (1 << 5), UART3_IER);	/* Set Maximum Received Frame size to 2048 bytes */	writeb(0x00, UART3_RXFLL);	writeb(0x08, UART3_RXFLH);	readb(UART3_RESUME);	__ECHO_OUT;	return 0;}staticint omap24xx_irda_shutdown(struct omap24xx_irda *si){	/* Disable all UART3 Interrupts */	writeb(0, UART3_IER);	/* Disable UART3 and disable baud rate generator */	writeb(0x07, UART3_MDR1);	/* Put UART3 in reset mode */	writeb((1 << 5), UART3_ACREG);	/* set SD_MODE pin to high and Disable RX IR */	/* Clear DLH and DLL */	writeb(1 << 7, UART3_LCR);	writeb(0, UART3_DLL);	writeb(0, UART3_DLH);	return 0;}static irqreturn_tomap24xx_irda_irq(int irq, void *dev_id, struct pt_regs *hw_regs){	struct net_device *dev = dev_id;	struct omap24xx_irda *si = dev->priv;	struct sk_buff *skb;	u8 status;	int w = 0;	__ECHO_IN;	/* Clear EOF interrupt */	status = readb(UART3_IIR);	if (status & (1 << 5)) {		u8 mdr2 = readb(UART3_MDR2);		if (mdr2 & 1)			printk(KERN_ERR "IRDA Buffer underrun error\n");		si->stats.tx_packets++;		if (si->newspeed) {			omap24xx_irda_set_speed(dev, si->newspeed);			si->newspeed = 0;		}		netif_wake_queue(dev);		if (!(status & 0x80))			return IRQ_HANDLED;	}	/* Stop DMA and if there are no errors, send frame to upper layer */	omap_stop_dma(si->rx_dma_channel);	status = readb(UART3_SFLSR);	/* Take a frame status */	if (status != 0) {	/* Bad frame? */		si->stats.rx_frame_errors++;		readb(UART3_RESUME);	} else {		/* We got a frame! */		skb = alloc_skb(4096, GFP_ATOMIC);		if (!skb) {			printk(KERN_ERR "omap_sir: out of memory for RX SKB\n");			return IRQ_HANDLED;		}		/*		 * Align any IP headers that may be contained		 * within the frame.		 */		skb_reserve(skb, 1);		w = readw(OMAP_DMA4_CDAC_REG(si->rx_dma_channel));		w -= readw(OMAP_DMA4_CDSA_REG(si->rx_dma_channel));		if (si->speed != 4000000) {			memcpy(skb_put(skb, w - 2), si->rx_buf_dma_virt, w - 2);	/* Copy DMA buffer to skb */		} else {			memcpy(skb_put(skb, w - 4), si->rx_buf_dma_virt, w - 4);	/* Copy DMA buffer to skb */		}		skb->dev = dev;		skb->mac.raw = skb->data;		skb->protocol = htons(ETH_P_IRDA);		si->stats.rx_packets++;		si->stats.rx_bytes += skb->len;		netif_receive_skb(skb);	/* Send data to upper level */	}	/* Re-init RX DMA */	omap24xx_irda_start_rx_dma(si);	dev->last_rx = jiffies;	__ECHO_OUT;	return IRQ_HANDLED;}staticint omap24xx_irda_hard_xmit(struct sk_buff *skb, struct net_device *dev){	struct omap24xx_irda *si = dev->priv;	int speed = irda_get_next_speed(skb);	int mtt = irda_get_mtt(skb);	int xbofs = irda_get_next_xbofs(skb);	__ECHO_IN;	/*	 * Does this packet contain a request to change the interface	 * speed?  If so, remember it until we complete the transmission	 * of this frame.	 */	if (speed != si->speed && speed != -1)		si->newspeed = speed;	if (xbofs) {		/* Set number of addtional BOFS */		writeb(xbofs + 1, UART3_EBLR);	}	/*	 * If this is an empty frame, we can bypass a lot.	 */	if (skb->len == 0) {		if (si->newspeed) {			si->newspeed = 0;			omap24xx_irda_set_speed(dev, speed);		}		dev_kfree_skb(skb);		return 0;	}	netif_stop_queue(dev);	/* Copy skb data to DMA buffer */	memcpy(si->tx_buf_dma_virt, skb->data, skb->len);	si->stats.tx_bytes += skb->len;	/* Set frame length */	writeb((skb->len & 0xff), UART3_TXFLL);	writeb((skb->len >> 8), UART3_TXFLH);	if (mtt > 1000)		mdelay(mtt / 1000);	else		udelay(mtt);	/* Start TX DMA transfer */	omap24xx_start_tx_dma(si, skb->len);	/* We can free skb now because it's already in DMA buffer */	dev_kfree_skb(skb);	dev->trans_start = jiffies;	__ECHO_OUT;	return 0;}static intomap24xx_irda_ioctl(struct net_device *dev, struct ifreq *ifreq, int cmd){	struct if_irda_req *rq = (struct if_irda_req *)ifreq;	struct omap24xx_irda *si = dev->priv;	int ret = -EOPNOTSUPP;	__ECHO_IN;	switch (cmd) {	case SIOCSBANDWIDTH:		if (capable(CAP_NET_ADMIN)) {			/*			 * We are unable to set the speed if the			 * device is not running.			 */			if (si->open) {				ret =				    omap24xx_irda_set_speed(dev,							    rq->ifr_baudrate);			} else {				printk				    (KERN_ERR				     "omap_irda_ioctl: SIOCSBANDWIDTH: !netif_running\n");				ret = 0;			}		}		break;

⌨️ 快捷键说明

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