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

📄 omap1610-ir.c

📁 Linux Kernel 2.6.9 for OMAP1710
💻 C
📖 第 1 页 / 共 2 页
字号:
			 * We are unable to set the speed if the			 * device is not running.			 */			if (si->open) {				ret =				    omap1610_irda_set_speed(dev,							    rq->ifr_baudrate);			} else {				printk				    (KERN_ERR				     "omap_irda_ioctl: SIOCSBANDWIDTH: !netif_running\n");				ret = 0;			}		}		break;	case SIOCSMEDIABUSY:		ret = -EPERM;		if (capable(CAP_NET_ADMIN)) {			irda_device_set_media_busy(dev, TRUE);			ret = 0;		}		break;	case SIOCGRECEIVING:		rq->ifr_receiving = rx_state;		break;	default:		break;	}	__ECHO_OUT;	return ret;}static struct net_device_stats *omap1610_irda_stats(struct net_device *dev){	struct omap1610_irda *si = dev->priv;	return &si->stats;}static int omap1610_irda_start(struct net_device *dev){	struct omap1610_irda *si = dev->priv;	int err;	unsigned long flags = 0;#ifdef CONFIG_MACH_OMAP_H3	u8 ioExpanderVal = 0;#endif	__ECHO_IN;	si->speed = 9600;	err = request_irq(dev->irq, omap1610_irda_irq, 0, dev->name, dev);	if (err)		goto err_irq;	/*	 * The interrupt must remain disabled for now.	 */	disable_irq(dev->irq);	/*  Request DMA channels for IrDA hardware */	if (omap_request_dma(OMAP_DMA_UART3_RX, "IrDA Rx DMA",			     (void *)omap1610_irda_rx_dma_callback,			     dev, &(si->rx_dma_channel))) {		printk(KERN_ERR "Failed to request IrDA Rx DMA \n");		goto err_irq;	}	if (omap_request_dma(OMAP_DMA_UART3_TX, "IrDA Tx DMA",			     (void *)omap1610_irda_tx_dma_callback,			     dev, &(si->tx_dma_channel))) {		printk(KERN_ERR "Failed to request IrDA Tx DMA \n");		goto err_irq;	}	/* Allocate TX and RX buffers for DMA channels */	si->rx_buf_dma_virt =	    dma_alloc_coherent(NULL, 4096, &(si->rx_buf_dma_phys), flags);	si->tx_buf_dma_virt =	    dma_alloc_coherent(NULL, 4096, &(si->tx_buf_dma_phys), flags);	/*	 * Setup the serial port for the specified config.	 */#if CONFIG_MACH_OMAP_H3	if ((err = read_gpio_expa(&ioExpanderVal, 0x26))) {		printk(KERN_ERR "Error reading from I/O EXPANDER \n");		return err;	}	ioExpanderVal |= 0x40;	/* 'P6' Enable IRDA_TX and IRDA_RX */	if ((err = write_gpio_expa(ioExpanderVal, 0x26))) {		printk(KERN_ERR "Error writing to I/O EXPANDER \n");		return err;	}#endif	err = omap1610_irda_startup(dev);	if (err)		goto err_startup;	omap1610_irda_set_speed(dev, si->speed = 9600);	/*	 * Open a new IrLAP layer instance.	 */	si->irlap = irlap_open(dev, &si->qos, "omap_sir");	err = -ENOMEM;	if (!si->irlap)		goto err_irlap;	/* Now enable the interrupt and start the queue  */	si->open = 1;	/* Start RX DMA */	omap1610_irda_start_rx_dma(si);	enable_irq(dev->irq);	netif_start_queue(dev);	__ECHO_OUT;	return 0;      err_irlap:	si->open = 0;	omap1610_irda_shutdown(si);      err_startup:      err_irq:	free_irq(dev->irq, dev);	MOD_DEC_USE_COUNT;	return err;}static int omap1610_irda_stop(struct net_device *dev){	struct omap1610_irda *si = dev->priv;	__ECHO_IN;	disable_irq(dev->irq);	netif_stop_queue(dev);	omap_free_dma(si->rx_dma_channel);	omap_free_dma(si->tx_dma_channel);	dma_free_coherent(NULL, 4096, si->rx_buf_dma_virt, si->rx_buf_dma_phys);	dma_free_coherent(NULL, 4096, si->tx_buf_dma_virt, si->tx_buf_dma_phys);	omap1610_irda_shutdown(si);	/* Stop IrLAP */	if (si->irlap) {		irlap_close(si->irlap);		si->irlap = NULL;	}	si->open = 0;	/*	 * Free resources	 */	free_irq(dev->irq, dev);	__ECHO_OUT;	return 0;}#ifdef CONFIG_MACH_OMAP_H3static void set_h3_gpio_expa(u8 FIR_SEL, u8 IrDA_INVSEL){	u8 ioExpanderVal = 0;	if (read_gpio_expa(&ioExpanderVal, 0x27) != 0) {		printk(KERN_ERR "Error reading from I/O EXPANDER \n");		return;	}	ioExpanderVal &= ~0x03;	ioExpanderVal |= FIR_SEL << 1;	ioExpanderVal |= IrDA_INVSEL << 0;	if (write_gpio_expa(ioExpanderVal, 0x27) != 0) {		printk(KERN_ERR "Error writing to I/O EXPANDER \n");		return;	}	if (read_gpio_expa(&ioExpanderVal, 0x27) != 0) {		printk(KERN_ERR "Error reading from I/O EXPANDER \n");		return;	}}int which_speed;static void set_h3_gpio_expa_handler(void *data){	int *mode = data;	if (*mode == SIR_MODE)		set_h3_gpio_expa(0, 1);	else if (*mode == MIR_MODE)		set_h3_gpio_expa(1, 1);	else if (*mode == FIR_MODE)		set_h3_gpio_expa(1, 1);}DECLARE_WORK(set_h3_gpio_expa_work, &set_h3_gpio_expa_handler, &which_speed);static inline void set_h3_irda_mode(int mode){	cancel_delayed_work(&set_h3_gpio_expa_work);	which_speed = mode;	schedule_work(&set_h3_gpio_expa_work);}#else#define set_h3_irda_mode(x)#endifstatic int omap1610_irda_set_speed(struct net_device *dev, int speed){	struct omap1610_irda *si = dev->priv;	int divisor;	__ECHO_IN;	/* Set IrDA speed */	if (speed <= 115200) {		/* SIR mode */		if (machine_is_omap_h2()) {			omap_set_gpio_dataout(OMAP1610_H2_FIRSEL_GPIO, 0);		}		if (machine_is_omap_h3())			set_h3_irda_mode(SIR_MODE);		printk("Set SIR Mode! Speed: %d\n", speed);		omap_writeb(1, UART3_MDR1);	/* Set SIR mode */		omap_writeb(1, UART3_EBLR);		divisor = 48000000 / (16 * speed);	/* Base clock 48 MHz */		HDBG2(1);		omap_writeb(1 << 7, UART3_LCR);		omap_writeb((divisor & 0xFF), UART3_DLL);		omap_writeb((divisor >> 8), UART3_DLH);		omap_writeb(0x03, UART3_LCR);		omap_writeb(0, UART3_MCR);		HDBG2(1);	} else if (speed <= 1152000) {		/* MIR mode */		printk("Set MIR Mode! Speed: %d\n", speed);		omap_writeb((1 << 2) | (1 << 6), UART3_MDR1);	/* Set MIR mode with 								   SIP after each frame */		omap_writeb(2, UART3_EBLR);		divisor = 48000000 / (41 * speed);	/* Base clock 48 MHz */		omap_writeb(1 << 7, UART3_LCR);		omap_writeb((divisor & 0xFF), UART3_DLL);		omap_writeb((divisor >> 8), UART3_DLH);		omap_writeb(0x03, UART3_LCR);		if (machine_is_omap_h2())			omap_set_gpio_dataout(OMAP1610_H2_FIRSEL_GPIO, 1);		if (machine_is_omap_h3())			set_h3_irda_mode(MIR_MODE);	} else {		/* FIR mode */		printk("Set FIR Mode! Speed: %d\n", speed);		omap_writeb((1 << 2) | (1 << 6) | 1, UART3_MDR1);	/* Set FIR mode									   with SIP after each frame */		if (machine_is_omap_h2())			omap_set_gpio_dataout(OMAP1610_H2_FIRSEL_GPIO, 1);		if (machine_is_omap_h3())			set_h3_irda_mode(FIR_MODE);	}	si->speed = speed;	__ECHO_OUT;	return 0;}#ifdef CONFIG_PM/* * Suspend the IrDA interface. */static int omap1610_irda_suspend(struct device *_dev, u32 state, u32 level){	struct net_device *dev = dev_get_drvdata(_dev);	struct omap1610_irda *si;	if (!dev || level != SUSPEND_DISABLE)		return 0;	si = (struct omap1610_irda *)&dev->priv;	if (si->open) {		/*		 * Stop the transmit queue		 */		netif_device_detach(dev);		disable_irq(dev->irq);		omap1610_irda_shutdown(si);	}	return 0;}/* * Resume the IrDA interface. */static int omap1610_irda_resume(struct device *_dev, u32 level){	struct net_device *dev = dev_get_drvdata(_dev);	struct omap1610_irda *si;	if (!dev || level != RESUME_ENABLE)		return 0;	si = (struct omap1610_irda *)&dev->priv;	if (si->open) {		/*		 * If we missed a speed change, initialise at the new speed		 * directly.  It is debatable whether this is actually		 * required, but in the interests of continuing from where		 * we left off it is desireable.  The converse argument is		 * that we should re-negotiate at 9600 baud again.		 */		if (si->newspeed) {			si->speed = si->newspeed;			si->newspeed = 0;		}		omap1610_irda_startup(dev);		enable_irq(dev->irq);		/*		 * This automatically wakes up the queue		 */		netif_device_attach(dev);	}	return 0;}#else#define omap1610_irda_suspend	NULL#define omap1610_irda_resume	NULL#endifstatic int omap1610_irda_probe(struct device *_dev){	struct platform_device *pdev = to_platform_device(_dev);	struct net_device *dev;	struct omap1610_irda *si;	unsigned int baudrate_mask;	int err = 0;	dev = alloc_irdadev(sizeof(struct omap1610_irda));	if (!dev)		goto err_mem_1;	si = dev->priv;	si->dev = &pdev->dev;	dev->hard_start_xmit = omap1610_irda_hard_xmit;	dev->open = omap1610_irda_start;	dev->stop = omap1610_irda_stop;	dev->do_ioctl = omap1610_irda_ioctl;	dev->get_stats = omap1610_irda_stats;	dev->irq = INT_UART3;	irda_init_max_qos_capabilies(&si->qos);	/*	 *  OMAP1610  supports SIR, MIR, FIR modes,	 *  but actualy supported modes depend on hardware implementation.	 *  OMAP1610 Innovator supports only SIR and 	 *  OMAP1610 H2 supports both SIR and FIR	 */	baudrate_mask =	    IR_9600 | IR_19200 | IR_38400 | IR_57600 | IR_115200 | IR_576000 |	    IR_1152000;	if (machine_is_omap_h2() || machine_is_omap_h3()) {		baudrate_mask |= (IR_4000000 << 8);	}	si->qos.baud_rate.bits &= baudrate_mask;	si->qos.min_turn_time.bits = 7;	irda_qos_bits_to_value(&si->qos);	err = register_netdev(dev);	if (!err)		dev_set_drvdata(&pdev->dev, dev);	else 		free_netdev(dev);      err_mem_1:	return err;}static int omap1610_irda_remove(struct device *_dev){	struct net_device *dev = dev_get_drvdata(_dev);	#ifdef CONFIG_MACH_OMAP_H3	if (machine_is_omap_h3())		cancel_delayed_work(&set_h3_gpio_expa_work);#endif	if (dev) {		unregister_netdev(dev);		free_netdev(dev);	}	return 0;}static void irda_dummy_release(struct device *dev){	/* Dummy function to keep the platform driver happy */}static struct device_driver omap1610ir_driver = {	.name = "omap1610-ir",	.bus = &platform_bus_type,	.probe = omap1610_irda_probe,	.remove = omap1610_irda_remove,	.suspend = omap1610_irda_suspend,	.resume = omap1610_irda_resume,};static struct platform_device omap1610ir_device = {	.name = "omap1610-ir",	.dev.release = irda_dummy_release,	.id = 0,};#ifdef MODULEstatic#endifint __init omap1610_irda_init(void){	int ret;	ret = driver_register(&omap1610ir_driver);	if (ret == 0) {		ret = platform_device_register(&omap1610ir_device);		if (ret)			driver_unregister(&omap1610ir_driver);	}	return ret;}#ifdef MODULEstatic#endifvoid __exit omap1610_irda_exit(void){	driver_unregister(&omap1610ir_driver);	platform_device_unregister(&omap1610ir_device);}module_init(omap1610_irda_init);module_exit(omap1610_irda_exit);MODULE_AUTHOR("MontaVista");MODULE_DESCRIPTION("OMAP IrDA Driver");MODULE_LICENSE("GPL");

⌨️ 快捷键说明

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