免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1159 | 回复: 0
打印 上一主题 下一主题

obt9700_relay [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2011-12-23 02:53 |只看该作者 |倒序浏览
  1. #include <linux/module.h>
  2. #include <linux/fs.h>
  3. #include <linux/delay.h>
  4. #include <linux/interrupt.h>
  5. #include <linux/cdev.h>
  6. #include <linux/input.h>

  7. #include <asm/uaccess.h>
  8. #include <asm/arch/hardware.h>
  9. #include <asm/io.h>

  10. #include <asm/arch/w90x900_reg.h>

  11. #define RELAY_MAJOR            (81)
  12. #define DEV_NAME            "relay"
  13. #define RELAY_DEVICE_NUMBER        MKDEV(RELAY_MAJOR, 0)

  14. #define SPEAKER_CTRL            (0x00)
  15. /* the speaker is on when arg is a non-zero value */

  16. #define RELAY1_CTRL            (0x01)
  17. /* the relay1 is on when arg is a non-zero value */

  18. #define RELAY2_CTRL            (0x02)
  19. /* the relay2 is on when arg is a non-zero value */

  20. #define RELAY3_CTRL            (0x03)
  21. /* the relay3 is on when arg is a non-zero value */

  22. #define RELAY4_CTRL            (0x04)
  23. /* the relay4 is on when arg is a non-zero value */

  24. /*
  25. hardware definitions.
  26.     SPEAKER        <=>        GPIO E13
  27.     RELAY1        <=>        GPIO E7
  28.     RELAY2        <=>        GPIO E6
  29.     RELAY3        <=>        GPIO D4
  30.     RELAY4        <=>        GPIO D8

  31.     ALARM_1        <=>        GPIO G2
  32.     ALARM_2        <=>        GPIO G3
  33. */

  34. struct obt9700relay_dev_t
  35. {
  36.     struct cdev        cdev_;
  37.     struct input_dev *    input;

  38.     struct tasklet_struct    tasklet_alarm;
  39.     unsigned char         alarmvalue;
  40. } obt9700relay_dev;

  41. static int obt9700_relay_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
  42. {
  43.     switch (cmd)
  44.     {
  45.         case SPEAKER_CTRL:
  46.             if (arg)
  47.             {
  48.                 outl(inl(REG_GPIOE_DATAOUT) | (1 << 13), REG_GPIOE_DATAOUT); /*pull up SPEAKER (GPIO E13)*/
  49.             }
  50.             else
  51.             {
  52.                 outl(inl(REG_GPIOE_DATAOUT) & ~(1 << 13), REG_GPIOE_DATAOUT); /*pull down SPEAKER (GPIO E13)*/
  53.             };
  54.             return 0;
  55.             break;

  56.         case RELAY1_CTRL:
  57.             if (arg)
  58.             {
  59.                 outl(inl(REG_GPIOE_DATAOUT) | (1 << 7), REG_GPIOE_DATAOUT); /*pull up RELAY1 (GPIO E7)*/
  60.             }
  61.             else
  62.             {
  63.                 outl(inl(REG_GPIOE_DATAOUT) & ~(1 << 7), REG_GPIOE_DATAOUT); /*pull down RELAY1 (GPIO E7)*/
  64.             };
  65.             return 0;
  66.             break;

  67.         case RELAY2_CTRL:
  68.             if (arg)
  69.             {
  70.                 outl(inl(REG_GPIOE_DATAOUT) | (1 << 6), REG_GPIOE_DATAOUT); /*pull up RELAY2 (GPIO E6)*/
  71.             }
  72.             else
  73.             {
  74.                 outl(inl(REG_GPIOE_DATAOUT) & ~(1 << 6), REG_GPIOE_DATAOUT); /*pull down RELAY2 (GPIO E6)*/
  75.             };
  76.             return 0;
  77.             break;

  78.         case RELAY3_CTRL:
  79.             if (arg)
  80.             {
  81.                 outl(inl(REG_GPIOD_DATAOUT) | (1 << 4), REG_GPIOD_DATAOUT); /*pull up RELAY3 (GPIO D4)*/
  82.             }
  83.             else
  84.             {
  85.                 outl(inl(REG_GPIOD_DATAOUT) & ~(1 << 4), REG_GPIOD_DATAOUT); /*pull down RELAY3 (GPIO D4)*/
  86.             };
  87.             return 0;
  88.             break;

  89.         case RELAY4_CTRL:
  90.             if (arg)
  91.             {
  92.                 outl(inl(REG_GPIOD_DATAOUT) | (1 << 8), REG_GPIOD_DATAOUT); /*pull up RELAY4 (GPIO D8)*/
  93.             }
  94.             else
  95.             {
  96.                 outl(inl(REG_GPIOD_DATAOUT) & ~(1 << 8), REG_GPIOD_DATAOUT); /*pull down RELAY4 (GPIO D8)*/
  97.             };
  98.             return 0;
  99.             break;
  100.     };

  101.     return -EINVAL;
  102. }

  103. struct file_operations obt9700_relay_fops =
  104. {
  105.     owner:      THIS_MODULE,
  106.     ioctl:     obt9700_relay_ioctl,
  107. };

  108. static void alarm_tasklet(unsigned long arg)
  109. {
  110.     input_report_key(obt9700relay_dev.input, obt9700relay_dev.alarmvalue, 1);
  111.     input_report_key(obt9700relay_dev.input, obt9700relay_dev.alarmvalue, 0);
  112.     input_sync(obt9700relay_dev.input);
  113. };

  114. static irqreturn_t relay_irq(int irq, void *devid, struct pt_regs *regs)
  115. {
  116.     register long value_;
  117.     register unsigned char key_;
  118.     if (!(inl(REG_AIC_GASR) & (1 << 2)))
  119.         return IRQ_NONE;
  120.     
  121.     value_ = inl(REG_GPIOG_DATAIN);
  122.     key_ = 0;

  123.     /* ALARM_1    <=>    GPIO G2 */
  124.     if (value_ & (1 << 2)) key_ |= (1 << 0);

  125.     /* ALARM_2    <=>    GPIO G3 */
  126.     if (value_ & (1 << 3)) key_ |= (1 << 1);

  127.     obt9700relay_dev.alarmvalue = key_;
  128.     tasklet_schedule(&obt9700relay_dev.tasklet_alarm);

  129.     outl(1, REG_AIC_GSCR); /* complete irq */
  130.     outl(~0, REG_AIC_EOSCR); /* complete irq */

  131.     return IRQ_HANDLED;
  132. }

  133. static int __init obt9700_relay_init(void)
  134. {
  135.     int ret;

  136.     cdev_init(&obt9700relay_dev.cdev_, &obt9700_relay_fops);
  137.     obt9700relay_dev.cdev_.owner = THIS_MODULE;

  138.     if ((ret = register_chrdev_region(RELAY_DEVICE_NUMBER, 1, DEV_NAME)) < 0)
  139.         return ret;

  140.     if ((ret = cdev_add(&obt9700relay_dev.cdev_, RELAY_DEVICE_NUMBER, 1)) != 0)
  141.         return ret;

  142.     /* configure input_event */
  143.     if (!(obt9700relay_dev.input = input_allocate_device()))
  144.     {
  145.         printk("Obt9700 relay: allocate memory failed!\n");
  146.         return -ENOMEM;
  147.     }
  148.     
  149.     obt9700relay_dev.input->name = "Obt9700Relay";
  150.     obt9700relay_dev.input->phys = "input/event1";
  151.     obt9700relay_dev.input->id.bustype = BUS_HOST;
  152.     obt9700relay_dev.input->id.vendor = 0x0005;
  153.     obt9700relay_dev.input->id.product = 0x0002;
  154.     obt9700relay_dev.input->id.version = 0x0100;

  155.     obt9700relay_dev.input->evbit[0] = BIT(EV_KEY) | BIT(EV_REP) | BIT(EV_SYN);
  156.         
  157.     set_bit(0x01, obt9700relay_dev.input->keybit);
  158.     set_bit(0x02, obt9700relay_dev.input->keybit);

  159.     input_register_device(obt9700relay_dev.input);

  160.     /* initialize the tasklet */
  161.     tasklet_init(&obt9700relay_dev.tasklet_alarm, alarm_tasklet, 0);

  162.     /* config the io pins(D4, D8) as output */
  163.     outl(inl(REG_MFSEL) & ~0x00f0, REG_MFSEL);        /* configure GPIOD to IO function. */
  164.     outl(inl(REG_GPIOD_DIR) | 0x0110, REG_GPIOD_DIR);    /* configure output pins. */
  165.     outl(inl(REG_GPIODPE) | 0x0110, REG_GPIODPE);        /* configure pins as pullup. */

  166.     /* config the io pins(E6, E7, E13) as output */
  167.     outl(inl(REG_MFSEL) & ~0x3c00, REG_MFSEL);        /* configure GPIOE to IO function. */
  168.     outl(inl(REG_GPIOE_DIR) | 0x20c0, REG_GPIOE_DIR);    /* configure output pins. */
  169.     outl(inl(REG_GPIOEPE) | 0x20c0, REG_GPIOEPE);        /* configure pins as pullup. */

  170.     /* config the io pins(G2 G3) as input */
  171.     outl(inl(REG_MFSEL) & ~0x00030000, REG_MFSEL);        /* configure GPIOG to IO function. */
  172.     outl(inl(REG_GPIOG_DIR) & ~0x000c, REG_GPIOG_DIR);    /* configure input pins. */

  173.     /* configure the nIRQ[2] to fall, enable */
  174.     outl(inl(REG_GPIOH_DIR) & ~(1 << 2), REG_GPIOH_DIR); /* configure GPIOH as input pin */

  175.     outl(inl(REG_MFSEL) | (1 << 24), REG_MFSEL);    /* configure GPIOH to nIRQ[2:0] mode*/

  176.     outl(((inl(REG_AIC_IRQSC) & (~0x30)) | (2)), REG_AIC_IRQSC); /* negative edge (fall pluse)*/

  177.     outl(inl(REG_AIC_GEN) | (1 << 2), REG_AIC_GEN); /* enable nIRQ[2]*/

  178.     /* request ext int0 down interrupt */
  179.     ret = request_irq(IRQ_GROUP0, relay_irq, SA_SHIRQ | SA_INTERRUPT, DEV_NAME, &obt9700relay_dev);
  180.     if (ret)
  181.     {
  182.         printk("Relay on obt9700 board driver: unable to grab Ext2 interrupt: %d\n", ret);
  183.         goto fail;
  184.     }

  185.     printk("Relay on obt9700 board driver started successfully!\n");

  186. fail:
  187.     input_free_device(obt9700relay_dev.input);
  188.     return(0);
  189. }

  190. static void __exit obt9700_relay_exit(void)
  191. {
  192.     free_irq(IRQ_GROUP0, &obt9700relay_dev);

  193.     input_unregister_device(obt9700relay_dev.input);

  194.     input_free_device(obt9700relay_dev.input);

  195.     cdev_del(&obt9700relay_dev.cdev_);

  196.     unregister_chrdev_region(RELAY_DEVICE_NUMBER, 1);
  197. }

  198. module_init(relay_init);
  199. module_exit(relay_exit);

  200. MODULE_AUTHOR("Adem");
  201. MODULE_DESCRIPTION("Relay driver on board");
  202. MODULE_LICENSE("GPL");
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP