📄 omap24xx-ir.c
字号:
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 *omap24xx_irda_stats(struct net_device *dev){ struct omap24xx_irda *si = dev->priv; return &si->stats;}#if 1staticint omap24xx_irda_setup(void){ omap2_cfg_reg(K15_2420_UART3_TX); omap2_cfg_reg(K14_2420_UART3_RX);#if 0 reg_val = omap_prcmreg_read(PRCM_FCLK_EN2_CORE); omap_prcmreg_write(reg_val | (1 << 2), PRCM_FCLK_EN2_CORE); reg_val = omap_prcmreg_read(PRCM_ICLK_EN2_CORE); omap_prcmreg_write(reg_val | (1 << 2), PRCM_ICLK_EN2_CORE);#endif}#endifstaticint omap24xx_irda_start(struct net_device *dev){ struct omap24xx_irda *si = dev->priv; int err; unsigned long flags = 0; u8 ioExpanderVal = 0; __ECHO_IN; si->speed = 9600; omap24xx_irda_setup(); err = request_irq(dev->irq, omap24xx_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(OMAP24XX_TRIGGER_RX, "IrDA Rx DMA", (void *)omap24xx_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(OMAP24XX_TRIGGER_TX, "IrDA Tx DMA", (void *)omap24xx_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 ((err = read_gpio_expa(&ioExpanderVal, 0x21))) { printk(KERN_ERR ": Error reading from I/O EXPANDER \n"); return err; } ioExpanderVal |= 0x01; /* 'P6' Enable IRDA_TX and IRDA_RX */ if ((err = write_gpio_expa(ioExpanderVal, 0x21))) { printk(KERN_ERR ": Error writing to I/O EXPANDER \n"); return err; } if ((err = read_gpio_expa(&ioExpanderVal, 0x21))) { printk(KERN_ERR " Error reading from I/O EXPANDER \n"); return err; } err = omap24xx_irda_startup(dev); if (err) goto err_startup; omap24xx_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 */ omap24xx_irda_start_rx_dma(si); enable_irq(dev->irq); netif_start_queue(dev); __ECHO_OUT; return 0; err_irlap: si->open = 0; omap24xx_irda_shutdown(si); err_startup: err_irq: free_irq(dev->irq, dev); MOD_DEC_USE_COUNT; return err;}staticint omap24xx_irda_stop(struct net_device *dev){ struct omap24xx_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); omap24xx_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;}static void set_h4_gpio_expa(u8 FIR_SEL){ u8 ioExpanderVal = 0; if (read_gpio_expa(&ioExpanderVal, 0x20) != 0) { printk("Error reading from I/O EXPANDER \n"); return; } ioExpanderVal &= ~0x01; ioExpanderVal |= FIR_SEL; if (write_gpio_expa(ioExpanderVal, 0x20) != 0) { printk("Error writing to I/O EXPANDER \n"); return; } if (read_gpio_expa(&ioExpanderVal, 0x20) != 0) { printk("Error reading from I/O EXPANDER \n"); return; }}static int which_speed;static void set_h4_gpio_expa_handler(void *data){ int *mode = data; if (*mode == SIR_MODE) set_h4_gpio_expa(0); else if (*mode == MIR_MODE) set_h4_gpio_expa(1); else if (*mode == FIR_MODE) set_h4_gpio_expa(1);}DECLARE_WORK(set_h4_gpio_expa_work, &set_h4_gpio_expa_handler, &which_speed);staticint omap24xx_irda_set_speed(struct net_device *dev, int speed){ struct omap24xx_irda *si = dev->priv; int divisor; __ECHO_IN; /* Set IrDA speed */ if (speed <= 115200) { if (in_interrupt()) { cancel_delayed_work(&set_h4_gpio_expa_work); which_speed = SIR_MODE; schedule_work(&set_h4_gpio_expa_work); } else set_h4_gpio_expa(0); /* SIR mode */ printk("Set SIR Mode! Speed: %d\n", speed); writeb(1, UART3_MDR1); /* Set SIR mode */ writeb(1, UART3_EBLR); divisor = BASE_CLK / (16 * speed); /* Base clock 48 MHz */ writeb(1 << 7, UART3_LCR); writeb((divisor & 0xFF), UART3_DLL); writeb((divisor >> 8), UART3_DLH); writeb(0x03, UART3_LCR); writeb(0, UART3_MCR); } else if (speed <= 1152000) { printk("Set MIR Mode! Speed: %d\n", speed); writeb((1 << 2) | (1 << 6), UART3_MDR1); /* Set MIR mode with SIP after each frame */ writeb(2, UART3_EBLR); divisor = BASE_CLK / (41 * speed); writeb(1 << 7, UART3_LCR); writeb((divisor & 0xFF), UART3_DLL); writeb((divisor >> 8), UART3_DLH); writeb(0x03, UART3_LCR); if (in_interrupt()) { cancel_delayed_work(&set_h4_gpio_expa_work); which_speed = MIR_MODE; schedule_work(&set_h4_gpio_expa_work); } else set_h4_gpio_expa(1); } else { /* FIR mode */ if (in_interrupt()) { cancel_delayed_work(&set_h4_gpio_expa_work); which_speed = MIR_MODE; schedule_work(&set_h4_gpio_expa_work); } else set_h4_gpio_expa(1); printk("Set FIR Mode! Speed: %d\n", speed); writeb((1 << 2) | (1 << 6) | 1, UART3_MDR1); /* Set FIR mode with SIP after each frame */ } si->speed = speed; __ECHO_OUT; return 0;}staticint omap24xx_irda_net_init(struct net_device *dev){ struct omap24xx_irda *si = dev->priv; unsigned int baudrate_mask; int err = -ENOMEM; si = kmalloc(sizeof(struct omap24xx_irda), GFP_KERNEL); if (!si) goto out; memset(si, 0, sizeof(*si)); /* * Initialize structures */ dev->priv = si; dev->hard_start_xmit = omap24xx_irda_hard_xmit; dev->open = omap24xx_irda_start; dev->stop = omap24xx_irda_stop; dev->do_ioctl = omap24xx_irda_ioctl; dev->get_stats = omap24xx_irda_stats; irda_device_setup(dev); irda_init_max_qos_capabilies(&si->qos); baudrate_mask = IR_9600 | IR_19200 | IR_38400 | IR_57600 | IR_115200; baudrate_mask |= (IR_4000000 << 8); si->qos.baud_rate.bits &= baudrate_mask; si->qos.min_turn_time.bits = 7; uart3_base = (unsigned long)ioremap(OMAP2420_UART3_BASE, OMAP24XX_REG_SIZE); irda_qos_bits_to_value(&si->qos); return 0; out: kfree(si); return err;}/* * Remove all traces of this driver module from the kernel, so we can't be * called. Note that the device has already been stopped, so we don't have * to worry about interrupts or dma. */static void omap24xx_irda_net_uninit(struct net_device *dev){ struct omap24xx_irda *si = dev->priv; dev->hard_start_xmit = NULL; dev->open = NULL; dev->stop = NULL; dev->do_ioctl = NULL; dev->get_stats = NULL; dev->priv = NULL; kfree(si);}#ifdef MODULEstatic#endifint __init omap24xx_irda_init(void){ struct net_device *dev; int err = 0; /* OMAP24xx IR net device register stage */ dev = alloc_irdadev(sizeof(struct omap24xx_irda)); if (dev) { dev->irq = INT_IRDA; dev->init = omap24xx_irda_net_init; dev->uninit = omap24xx_irda_net_uninit; err = register_netdev(dev); if (err) { kfree(dev); } else { netdev = dev; } } return err;}#ifdef MODULEstatic#endifvoid __exit omap24xx_irda_exit(void){ struct net_device *dev = netdev; if (dev) { unregister_netdev(dev); free_netdev(dev); } /* * We now know that the netdevice is no longer in use, and all * references to our driver have been removed. The only structure * which may still be present is the netdevice, which will get * cleaned up by net/core/dev.c */}int write_gpio_expa(u8 val, int addr){ struct i2c_adapter *adap; int err; struct i2c_msg msg[1]; unsigned char data[1]; adap = i2c_get_adapter(0); if (!adap) return -ENODEV; msg->addr = addr; /* I2C address of GPIO EXPA */ msg->flags = 0; msg->len = 1; msg->buf = data; data[0] = val; err = i2c_transfer(adap, msg, 1); if (err >= 0) return 0; return err;}int read_gpio_expa(u8 * val, int addr){ struct i2c_adapter *adap; int err; struct i2c_msg msg[1]; unsigned char data[1]; adap = i2c_get_adapter(0); if (!adap) return -ENODEV; msg->addr = addr; /* I2C address of GPIO EXPA */ msg->flags = I2C_M_RD; msg->len = 2; msg->buf = data; err = i2c_transfer(adap, msg, 1); *val = data[0]; printk("IRDA: I2C: Read data is %x", (u8) * data); if (err >= 0) return 0; return err;}module_init(omap24xx_irda_init);module_exit(omap24xx_irda_exit);MODULE_AUTHOR("MontaVista");MODULE_DESCRIPTION("OMAP24XX IR");MODULE_LICENSE("GPL");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -