- 论坛徽章:
- 0
|
- #include <linux/module.h>
- #include <linux/fs.h>
- #include <linux/delay.h>
- #include <linux/interrupt.h>
- #include <linux/cdev.h>
- #include <linux/input.h>
- #include <asm/uaccess.h>
- #include <asm/arch/hardware.h>
- #include <asm/io.h>
- #include <asm/arch/w90x900_reg.h>
- #define RELAY_MAJOR (81)
- #define DEV_NAME "relay"
- #define RELAY_DEVICE_NUMBER MKDEV(RELAY_MAJOR, 0)
- #define SPEAKER_CTRL (0x00)
- /* the speaker is on when arg is a non-zero value */
- #define RELAY1_CTRL (0x01)
- /* the relay1 is on when arg is a non-zero value */
- #define RELAY2_CTRL (0x02)
- /* the relay2 is on when arg is a non-zero value */
- #define RELAY3_CTRL (0x03)
- /* the relay3 is on when arg is a non-zero value */
- #define RELAY4_CTRL (0x04)
- /* the relay4 is on when arg is a non-zero value */
- /*
- hardware definitions.
- SPEAKER <=> GPIO E13
- RELAY1 <=> GPIO E7
- RELAY2 <=> GPIO E6
- RELAY3 <=> GPIO D4
- RELAY4 <=> GPIO D8
- ALARM_1 <=> GPIO G2
- ALARM_2 <=> GPIO G3
- */
- struct obt9700relay_dev_t
- {
- struct cdev cdev_;
- struct input_dev * input;
- struct tasklet_struct tasklet_alarm;
- unsigned char alarmvalue;
- } obt9700relay_dev;
- static int obt9700_relay_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
- {
- switch (cmd)
- {
- case SPEAKER_CTRL:
- if (arg)
- {
- outl(inl(REG_GPIOE_DATAOUT) | (1 << 13), REG_GPIOE_DATAOUT); /*pull up SPEAKER (GPIO E13)*/
- }
- else
- {
- outl(inl(REG_GPIOE_DATAOUT) & ~(1 << 13), REG_GPIOE_DATAOUT); /*pull down SPEAKER (GPIO E13)*/
- };
- return 0;
- break;
- case RELAY1_CTRL:
- if (arg)
- {
- outl(inl(REG_GPIOE_DATAOUT) | (1 << 7), REG_GPIOE_DATAOUT); /*pull up RELAY1 (GPIO E7)*/
- }
- else
- {
- outl(inl(REG_GPIOE_DATAOUT) & ~(1 << 7), REG_GPIOE_DATAOUT); /*pull down RELAY1 (GPIO E7)*/
- };
- return 0;
- break;
- case RELAY2_CTRL:
- if (arg)
- {
- outl(inl(REG_GPIOE_DATAOUT) | (1 << 6), REG_GPIOE_DATAOUT); /*pull up RELAY2 (GPIO E6)*/
- }
- else
- {
- outl(inl(REG_GPIOE_DATAOUT) & ~(1 << 6), REG_GPIOE_DATAOUT); /*pull down RELAY2 (GPIO E6)*/
- };
- return 0;
- break;
- case RELAY3_CTRL:
- if (arg)
- {
- outl(inl(REG_GPIOD_DATAOUT) | (1 << 4), REG_GPIOD_DATAOUT); /*pull up RELAY3 (GPIO D4)*/
- }
- else
- {
- outl(inl(REG_GPIOD_DATAOUT) & ~(1 << 4), REG_GPIOD_DATAOUT); /*pull down RELAY3 (GPIO D4)*/
- };
- return 0;
- break;
- case RELAY4_CTRL:
- if (arg)
- {
- outl(inl(REG_GPIOD_DATAOUT) | (1 << 8), REG_GPIOD_DATAOUT); /*pull up RELAY4 (GPIO D8)*/
- }
- else
- {
- outl(inl(REG_GPIOD_DATAOUT) & ~(1 << 8), REG_GPIOD_DATAOUT); /*pull down RELAY4 (GPIO D8)*/
- };
- return 0;
- break;
- };
- return -EINVAL;
- }
- struct file_operations obt9700_relay_fops =
- {
- owner: THIS_MODULE,
- ioctl: obt9700_relay_ioctl,
- };
- static void alarm_tasklet(unsigned long arg)
- {
- input_report_key(obt9700relay_dev.input, obt9700relay_dev.alarmvalue, 1);
- input_report_key(obt9700relay_dev.input, obt9700relay_dev.alarmvalue, 0);
- input_sync(obt9700relay_dev.input);
- };
- static irqreturn_t relay_irq(int irq, void *devid, struct pt_regs *regs)
- {
- register long value_;
- register unsigned char key_;
- if (!(inl(REG_AIC_GASR) & (1 << 2)))
- return IRQ_NONE;
-
- value_ = inl(REG_GPIOG_DATAIN);
- key_ = 0;
- /* ALARM_1 <=> GPIO G2 */
- if (value_ & (1 << 2)) key_ |= (1 << 0);
- /* ALARM_2 <=> GPIO G3 */
- if (value_ & (1 << 3)) key_ |= (1 << 1);
- obt9700relay_dev.alarmvalue = key_;
- tasklet_schedule(&obt9700relay_dev.tasklet_alarm);
- outl(1, REG_AIC_GSCR); /* complete irq */
- outl(~0, REG_AIC_EOSCR); /* complete irq */
- return IRQ_HANDLED;
- }
- static int __init obt9700_relay_init(void)
- {
- int ret;
- cdev_init(&obt9700relay_dev.cdev_, &obt9700_relay_fops);
- obt9700relay_dev.cdev_.owner = THIS_MODULE;
- if ((ret = register_chrdev_region(RELAY_DEVICE_NUMBER, 1, DEV_NAME)) < 0)
- return ret;
- if ((ret = cdev_add(&obt9700relay_dev.cdev_, RELAY_DEVICE_NUMBER, 1)) != 0)
- return ret;
- /* configure input_event */
- if (!(obt9700relay_dev.input = input_allocate_device()))
- {
- printk("Obt9700 relay: allocate memory failed!\n");
- return -ENOMEM;
- }
-
- obt9700relay_dev.input->name = "Obt9700Relay";
- obt9700relay_dev.input->phys = "input/event1";
- obt9700relay_dev.input->id.bustype = BUS_HOST;
- obt9700relay_dev.input->id.vendor = 0x0005;
- obt9700relay_dev.input->id.product = 0x0002;
- obt9700relay_dev.input->id.version = 0x0100;
- obt9700relay_dev.input->evbit[0] = BIT(EV_KEY) | BIT(EV_REP) | BIT(EV_SYN);
-
- set_bit(0x01, obt9700relay_dev.input->keybit);
- set_bit(0x02, obt9700relay_dev.input->keybit);
- input_register_device(obt9700relay_dev.input);
- /* initialize the tasklet */
- tasklet_init(&obt9700relay_dev.tasklet_alarm, alarm_tasklet, 0);
- /* config the io pins(D4, D8) as output */
- outl(inl(REG_MFSEL) & ~0x00f0, REG_MFSEL); /* configure GPIOD to IO function. */
- outl(inl(REG_GPIOD_DIR) | 0x0110, REG_GPIOD_DIR); /* configure output pins. */
- outl(inl(REG_GPIODPE) | 0x0110, REG_GPIODPE); /* configure pins as pullup. */
- /* config the io pins(E6, E7, E13) as output */
- outl(inl(REG_MFSEL) & ~0x3c00, REG_MFSEL); /* configure GPIOE to IO function. */
- outl(inl(REG_GPIOE_DIR) | 0x20c0, REG_GPIOE_DIR); /* configure output pins. */
- outl(inl(REG_GPIOEPE) | 0x20c0, REG_GPIOEPE); /* configure pins as pullup. */
- /* config the io pins(G2 G3) as input */
- outl(inl(REG_MFSEL) & ~0x00030000, REG_MFSEL); /* configure GPIOG to IO function. */
- outl(inl(REG_GPIOG_DIR) & ~0x000c, REG_GPIOG_DIR); /* configure input pins. */
- /* configure the nIRQ[2] to fall, enable */
- outl(inl(REG_GPIOH_DIR) & ~(1 << 2), REG_GPIOH_DIR); /* configure GPIOH as input pin */
- outl(inl(REG_MFSEL) | (1 << 24), REG_MFSEL); /* configure GPIOH to nIRQ[2:0] mode*/
- outl(((inl(REG_AIC_IRQSC) & (~0x30)) | (2)), REG_AIC_IRQSC); /* negative edge (fall pluse)*/
- outl(inl(REG_AIC_GEN) | (1 << 2), REG_AIC_GEN); /* enable nIRQ[2]*/
- /* request ext int0 down interrupt */
- ret = request_irq(IRQ_GROUP0, relay_irq, SA_SHIRQ | SA_INTERRUPT, DEV_NAME, &obt9700relay_dev);
- if (ret)
- {
- printk("Relay on obt9700 board driver: unable to grab Ext2 interrupt: %d\n", ret);
- goto fail;
- }
- printk("Relay on obt9700 board driver started successfully!\n");
- fail:
- input_free_device(obt9700relay_dev.input);
- return(0);
- }
- static void __exit obt9700_relay_exit(void)
- {
- free_irq(IRQ_GROUP0, &obt9700relay_dev);
- input_unregister_device(obt9700relay_dev.input);
- input_free_device(obt9700relay_dev.input);
- cdev_del(&obt9700relay_dev.cdev_);
- unregister_chrdev_region(RELAY_DEVICE_NUMBER, 1);
- }
- module_init(relay_init);
- module_exit(relay_exit);
- MODULE_AUTHOR("Adem");
- MODULE_DESCRIPTION("Relay driver on board");
- MODULE_LICENSE("GPL");
|
|