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

📄 omap1610-ir.c

📁 Linux Kernel 2.6.9 for OMAP1710
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * BRIEF MODULE DESCRIPTION * *	Infra-red driver for the OMAP1610-H2 and OMAP1710-H3 Platforms *          (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).  Nov 2004, Texas Instruments - Modified by Manjunath GK for Power management support  */#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/mux.h>#include <asm/arch/gpio.h>#include <linux/i2c.h>#ifdef CONFIG_MACH_OMAP_H3#include <asm/arch/gpioexpander.h>#endif#define SIR_MODE 0#define MIR_MODE 1#define FIR_MODE 2#define OMAP1610_H2_FIRSEL_GPIO 17static int rx_state = 0;	/* RX state for IOCTL */struct omap1610_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;};#define OMAP_IRDA_DEBUG	0#if (OMAP_IRDA_DEBUG > 0)#define DBG(format, args...) printk(KERN_ERR "%s(): " format, __FUNCTION__, ## args);#define DBG_IRQ(format, args...) printk(KERN_ERR "%s(): " format, __FUNCTION__, ## args);#else#define DBG(format, args...)#define DBG_IRQ(format, args...)#endif#if (OMAP_IRDA_DEBUG > 1)#define __ECHO_IN printk(KERN_ERR "%s: enter\n",__FUNCTION__);#define __ECHO_OUT printk(KERN_ERR "%s: exit\n",__FUNCTION__);#else#define __ECHO_IN#define __ECHO_OUT#endif#ifdef OMAP1610_IR_HARDWARE_DEBUG_ENABLE#define HDBG_DELAY 200void hard_debug1(u16 i){	for (; i; i--) {		omap_writew(0x2000,			    OMAP1610_GPIO1_BASE + OMAP1610_GPIO_CLEAR_DATAOUT);		udelay(HDBG_DELAY);		omap_writew(0x2000,			    OMAP1610_GPIO1_BASE + OMAP1610_GPIO_SET_DATAOUT);		udelay(HDBG_DELAY);	}}void hard_debug2(u16 i){	for (; i; i--) {		omap_writew(0x8000,			    OMAP1610_GPIO1_BASE + OMAP1610_GPIO_CLEAR_DATAOUT);		udelay(HDBG_DELAY);		omap_writew(0x8000,			    OMAP1610_GPIO1_BASE + OMAP1610_GPIO_SET_DATAOUT);		udelay(HDBG_DELAY);	}}#define HDBG1(i) hard_debug1(i)#define HDBG2(i) hard_debug2(i)#else#define HDBG1(i)#define HDBG2(i)#endif/* forward declarations */extern void irda_device_setup(struct net_device *dev);extern void omap_stop_dma(int lch);static int omap1610_irda_set_speed(struct net_device *dev, int speed);static void omap1610_irda_start_rx_dma(struct omap1610_irda *si){	/* Configure DMA */	omap_set_dma_src_params(si->rx_dma_channel, 0x3, 0x0, (unsigned long)UART3_RHR);	omap_enable_dma_irq(si->rx_dma_channel, 0x01);	omap_set_dma_dest_params(si->rx_dma_channel, 0x0, 0x1,				 si->rx_buf_dma_phys);	omap_set_dma_transfer_params(si->rx_dma_channel, 0x0, 4096, 0x1, 0x0);	omap_start_dma(si->rx_dma_channel);}static void omap1610_start_tx_dma(struct omap1610_irda *si, int size){	__ECHO_IN;	/* Configure DMA */	omap_set_dma_dest_params(si->tx_dma_channel, 0x03, 0x0, (unsigned long)UART3_THR);	omap_enable_dma_irq(si->tx_dma_channel, 0x01);	omap_set_dma_src_params(si->tx_dma_channel, 0x0, 0x1,				si->tx_buf_dma_phys);	omap_set_dma_transfer_params(si->tx_dma_channel, 0x0, size, 0x1, 0x0);	HDBG1(1);	/* Start DMA */	omap_start_dma(si->tx_dma_channel);	HDBG1(1);	__ECHO_OUT;}/* DMA RX callback - normally, we should not go here,    it calls only if something is going wrong */static void omap1610_irda_rx_dma_callback(int lch, u16 ch_status, void *data){	struct net_device *dev = data;	struct omap1610_irda *si = dev->priv;	printk(KERN_ERR "RX Transfer error or very big frame \n");	/* Clear interrupts */	omap_readb(UART3_IIR);	si->stats.rx_frame_errors++;	omap_readb(UART3_RESUME);	/* Re-init RX DMA */	omap1610_irda_start_rx_dma(si);}/* DMA TX callback - calling when frame transfer has been finished */static void omap1610_irda_tx_dma_callback(int lch, u16 ch_status, void *data){	struct net_device *dev = data;	struct omap1610_irda *si = dev->priv;	__ECHO_IN;	/*Stop DMA controller */	omap_stop_dma(si->tx_dma_channel);	__ECHO_OUT;}/* * Set the IrDA communications speed. * Interrupt have to be disabled here. */static int omap1610_irda_startup(struct net_device *dev){	__ECHO_IN;	/* Enable UART3 clock and set UART3 to IrDA mode */	omap_writel(omap_readl(MOD_CONF_CTRL_0) | (1 << 31) | (1 << 15),		    MOD_CONF_CTRL_0);	if (machine_is_omap_h2()) {//              omap_cfg_reg(Y15_1610_GPIO17);		omap_writel(omap_readl(FUNC_MUX_CTRL_A) | 7, FUNC_MUX_CTRL_A);		omap_set_gpio_direction(OMAP1610_H2_FIRSEL_GPIO, 0);		omap_set_gpio_dataout(OMAP1610_H2_FIRSEL_GPIO, 0);	}	omap_writeb(0x07, UART3_MDR1);	/* Put UART3 in reset mode */	/* Clear DLH and DLL */	omap_writeb(1 << 7, UART3_LCR);	omap_writeb(0, UART3_DLL);	omap_writeb(0, UART3_DLH);	omap_writeb(0xbf, UART3_LCR);	omap_writeb(1 << 4, UART3_EFR);	omap_writeb(1 << 7, UART3_LCR);	/* Enable access to UART3_TLR and UART3_TCR registers */	omap_writeb(1 << 6, UART3_MCR);	omap_writeb(0, UART3_SCR);	/* Set Rx trigger to 1 and Tx trigger to 1 */	omap_writeb(0, UART3_TLR);	/* Set LCR to 8 bits and 1 stop bit */	omap_writeb(0x03, UART3_LCR);	/* Clear RX and TX FIFO and enable FIFO */	/* Use DMA Req for transfers */	omap_writeb((1 << 2) | (1 << 1) | (1 << 3) | (1 << 4) | (1 << 6) | 1,		    UART3_FCR);	omap_writeb(0, UART3_MCR);	omap_writeb((1 << 7) | (1 << 6), UART3_SCR);	/* Enable UART3 SIR Mode,(Frame-length method to end frames) */	omap_writeb(1, UART3_MDR1);	/* Set Status FIFO trig to 1 */	omap_writeb(0, UART3_MDR2);	/* Enables RXIR input */	/* and disable TX underrun */	/* SEND_SIP pulse */	//   omap_writeb((1 << 7) | (1 << 6) | (1 << 4), UART3_ACREG);	omap_writeb((1 << 6) | (1 << 4), UART3_ACREG);	/* Enable EOF Interrupt only */	omap_writeb((1 << 7) | (1 << 5), UART3_IER);	/* Set Maximum Received Frame size to 2048 bytes */	omap_writeb(0x00, UART3_RXFLL);	omap_writeb(0x08, UART3_RXFLH);	omap_readb(UART3_RESUME);	__ECHO_OUT;	return 0;}static int omap1610_irda_shutdown(struct omap1610_irda *si){	/* Disable all UART3 Interrupts */	omap_writeb(0, UART3_IER);	/* Disable UART3 and disable baud rate generator */	omap_writeb(0x07, UART3_MDR1);	/* Put UART3 in reset mode */	omap_writeb((1 << 5), UART3_ACREG);	/* set SD_MODE pin to high and Disable RX IR */	/* Clear DLH and DLL */	omap_writeb(1 << 7, UART3_LCR);	omap_writeb(0, UART3_DLL);	omap_writeb(0, UART3_DLH);	return 0;}static irqreturn_tomap1610_irda_irq(int irq, void *dev_id, struct pt_regs *hw_regs){	struct net_device *dev = dev_id;	struct omap1610_irda *si = dev->priv;	struct sk_buff *skb;	u8 status;	int w = 0;	__ECHO_IN;	/* Clear EOF interrupt */	status = omap_readb(UART3_IIR);	if (status & (1 << 5)) {		u8 mdr2 = omap_readb(UART3_MDR2);		HDBG1(2);		if (mdr2 & 1)			printk(KERN_ERR "IRDA Buffer underrun error");		si->stats.tx_packets++;		if (si->newspeed) {			omap1610_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 = omap_readb(UART3_SFLSR);	/* Take a frame status */	if (status != 0) {	/* Bad frame? */		si->stats.rx_frame_errors++;		omap_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 = omap_readw(OMAP_DMA_CDAC(si->rx_dma_channel));		w -= omap_readw(OMAP_DMA_CDSA_L(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 */	omap1610_irda_start_rx_dma(si);	dev->last_rx = jiffies;	__ECHO_OUT;	return IRQ_HANDLED;}static int omap1610_irda_hard_xmit(struct sk_buff *skb, struct net_device *dev){	struct omap1610_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 */		omap_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;			omap1610_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 */	omap_writeb((skb->len & 0xff), UART3_TXFLL);	omap_writeb((skb->len >> 8), UART3_TXFLH);	if (mtt > 1000)		mdelay(mtt / 1000);	else		udelay(mtt);	/* Start TX DMA transfer */	omap1610_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 intomap1610_irda_ioctl(struct net_device *dev, struct ifreq *ifreq, int cmd){	struct if_irda_req *rq = (struct if_irda_req *)ifreq;	struct omap1610_irda *si = dev->priv;	int ret = -EOPNOTSUPP;	__ECHO_IN;	switch (cmd) {	case SIOCSBANDWIDTH:		if (capable(CAP_NET_ADMIN)) {			/*

⌨️ 快捷键说明

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