Android linux PWM驱动(s5pv210)
16lz
2021-01-23
Android linux PWM驱动(s5pv210)
struct pwm_ctrl_dev{struct cdev cdev;struct pwm_device *pwm;int freq;unsigned int irq;unsigned char value;};static struct pwm_ctrl_dev *pwm_dev;struct class *pwm_class;static int major = DEVICE_MAJOR;static void pwm_set_freq(unsigned long freq) {int period_ns = NS_IN_1HZ / freq;pwm_config(pwm_dev->pwm, period_ns / 2, period_ns);pwm_enable(pwm_dev->pwm);}static void pwm_on(void){s3c_gpio_cfgpin(GPIO_DOUT, S3C_GPIO_SFN(2));pwm_set_freq(pwm_dev->freq);pwm_dev->value = 1;}static void pwm_off(void){s3c_gpio_cfgpin(GPIO_DOUT, S3C_GPIO_SFN(0));pwm_disable(pwm_dev->pwm);pwm_dev->value = 0;}static int pwm_ctrl_open(struct inode *inode, struct file *filp){try_module_get(THIS_MODULE);return 0;}static int pwm_ctrl_release(struct inode *inode,struct file *filp){module_put(THIS_MODULE);return 0;}static long pwm_ctrl_ioctl(struct file *filp, unsigned int cmd, unsigned long arg){switch (cmd) {case PWM_IOCTL_GET_STATE:if(copy_to_user((int __user*)arg,&pwm_dev->value, 1))return -ENOTTY;case PWM_IOCTL_GET_FREQ:if(copy_to_user((int __user*)arg,&pwm_dev->freq, sizeof(int)))return -ENOTTY; case PWM_IOCTL_SET_FREQ:if (arg == 0){pwm_off();return 0;}pwm_on();pwm_set_freq(arg);break;case PWM_IOCTL_STOP:default:pwm_off();break;}return 0;}static ssize_t pwm_ctrl_read(struct file *filp,char __user *buf,size_t size,loff_t *f_pos){put_user(pwm_dev->value, buf);return 0;}static ssize_t pwm_ctrl_write(struct file *filp,const char __user *buf,size_t size,loff_t *f_pos){get_user(pwm_dev->value, buf);if(pwm_dev->value) pwm_on();else pwm_off();return 0;}static struct file_operations pwm_ctrl_fops={.owner = THIS_MODULE,.read = pwm_ctrl_read,.write = pwm_ctrl_write,.unlocked_ioctl = pwm_ctrl_ioctl,.open = pwm_ctrl_open,.release = pwm_ctrl_release,};static void pwm_ctrl_setup_cdev(struct pwm_ctrl_dev *dev,int minor,struct file_operations *fops){int err, devno = MKDEV(major, minor);cdev_init(&(dev->cdev), fops);dev->cdev.owner = THIS_MODULE;dev->cdev.ops = fops;err=cdev_add(&(dev->cdev), devno, 1);if(err){printk(KERN_NOTICE"erro %d adding %s %d\n",err,DEVICE_NAME,minor);}}int __init pwm_ctrl_init(void){int result;dev_t devno=MKDEV(major,0);if(major){result = register_chrdev_region(devno, 1, DEVICE_NAME);}else{result = alloc_chrdev_region(&devno, 0, 1, DEVICE_NAME);}if(result < 0){printk(KERN_WARNING"%s: unable to get major %d\n",DEVICE_NAME,major);return result;}pwm_dev=kmalloc(sizeof(struct pwm_ctrl_dev),GFP_KERNEL);if(!pwm_dev){result=-ENOMEM;goto fail_malloc;}pwm_class = class_create(THIS_MODULE, DEVICE_NAME);device_create(pwm_class, NULL, MKDEV(DEVICE_MAJOR, 0), NULL, DEVICE_NAME);pwm_ctrl_setup_cdev(pwm_dev, 0, &pwm_ctrl_fops);pwm_dev->value = 0;pwm_dev->freq = 1000; result = gpio_request(GPIO_DOUT, DEVICE_NAME); if (result) {printk(KERN_INFO "[%s] request GPIO_DOUT for pwm failed\n", __func__);goto fail_malloc;} s3c_gpio_cfgpin(GPIO_DOUT, S3C_GPIO_SFN(1)); gpio_set_value(GPIO_DOUT, 0); pwm_dev->pwm = pwm_request(BUZZER_PWM_ID, "buzzer");if (IS_ERR(pwm_dev->pwm)){printk(KERN_INFO "[%s] %s\n", __func__, "unable to request PWM for Buzzer\n");goto fail_pwm;} pwm_off();return 0;fail_pwm:pwm_free(pwm_dev->pwm);kfree(pwm_dev);fail_malloc:unregister_chrdev_region(MKDEV(major,0),1);return result;}void __exit pwm_ctrl_exit(void){cdev_del(&pwm_dev->cdev);device_destroy(pwm_class, MKDEV(major, 0));class_destroy(pwm_class);pwm_off();pwm_free(pwm_dev->pwm);gpio_free(GPIO_DOUT);kfree(pwm_dev);unregister_chrdev_region(MKDEV(major, 0), 1);}module_init(pwm_ctrl_init);module_exit(pwm_ctrl_exit);MODULE_AUTHOR("jvaemape");MODULE_DESCRIPTION("S3C PWM Drive");MODULE_LICENSE("Dual BSD/GPL");
更多相关文章
- 代码中设置drawableleft
- android 3.0 隐藏 系统标题栏
- Android开发中activity切换动画的实现
- Android(安卓)学习 笔记_05. 文件下载
- Android中直播视频技术探究之—摄像头Camera视频源数据采集解析
- 技术博客汇总
- android 2.3 wifi (一)
- AndRoid Notification的清空和修改
- Android中的Chronometer