📄 s3c2410_pwm.c
字号:
#include <linux/kernel.h>#include <linux/init.h>#include <linux/module.h>#include <linux/ioport.h>#include <linux/miscdevice.h> #include <linux/sched.h> #include <linux/delay.h> #include <linux/poll.h> #include <linux/spinlock.h> #include <linux/delay.h> #include <linux/wait.h>#include <linux/device.h> #include <linux/devfs_fs_kernel.h> #include <linux/types.h> #include <linux/cdev.h> #include <linux/errno.h> #include <asm/uaccess.h> #include <asm/hardware.h>#include <asm/io.h>#include <asm/arch/regs-mem.h>#include <asm/arch/regs-gpio.h>#include <asm/arch-s3c2410/regs-timer.h>#include "s3c2410_pwm.h"#define DEVICE_NAME "pwm" static int pwm_major = 0;static int pwm_set_prescaler(struct PWM_CHANNEL *pwm){ writel( (readl(S3C2410_TCFG0)&0xffffff00) + (pwm->prescaler0&0xFF) ,S3C2410_TCFG0 ); return 0;}static int pwm_set_channel(unsigned char channel,struct PWM_CHANNEL *pwm){ unsigned long tmp; unsigned long tmp1; switch(channel) { case 0: pwm_set_prescaler(pwm); tmp = readl(S3C2410_TCFG1); tmp = (tmp & (~(0x0F<<0))) | ((pwm->div_clock&0x000F)<<0); writel(tmp, S3C2410_TCFG1); writel((pwm->tcntb_reg&0xFFFF), S3C2410_TCNTB(channel)); writel((pwm->tcmpb_reg&0xFFFF), S3C2410_TCMPB(channel)); tmp = readl(S3C2410_TCON) | S3C2410_TCON_T0RELOAD | S3C2410_TCON_T0MANUALUPD; tmp1 = (readl(S3C2410_TCON) | S3C2410_TCON_T0RELOAD) & (~S3C2410_TCON_T0MANUALUPD); writel(tmp, S3C2410_TCON); if(pwm->off) writel(tmp1&(~S3C2410_TCON_T0START), S3C2410_TCON); else writel(tmp1 | S3C2410_TCON_T0START, S3C2410_TCON); break; case 1: pwm_set_prescaler(pwm); tmp = readl(S3C2410_TCFG1); tmp = (tmp & (~(0x0F<<4))) | ((pwm->div_clock&0x000F)<<4); writel(tmp, S3C2410_TCFG1); writel((pwm->tcntb_reg&0xFFFF), S3C2410_TCNTB(channel)); writel((pwm->tcmpb_reg&0xFFFF), S3C2410_TCMPB(channel)); tmp = readl(S3C2410_TCON) | S3C2410_TCON_T1RELOAD | S3C2410_TCON_T1MANUALUPD; tmp1 = (readl(S3C2410_TCON) | S3C2410_TCON_T1RELOAD) & (~S3C2410_TCON_T1MANUALUPD); writel(tmp, S3C2410_TCON); if(pwm->off) writel(tmp1 & (~S3C2410_TCON_T1START), S3C2410_TCON); else writel(tmp1 | S3C2410_TCON_T1START, S3C2410_TCON); break; case 2: tmp = readl(S3C2410_TCFG1); tmp = (tmp & (~(0x0F<<8))) | ((pwm->div_clock&0x000F)<<8); writel(tmp, S3C2410_TCFG1); writel(pwm->tcntb_reg&0xFFFF, S3C2410_TCNTB(channel)); writel(pwm->tcmpb_reg&0xFFFF, S3C2410_TCMPB(channel)); tmp = readl(S3C2410_TCON) | S3C2410_TCON_T2RELOAD | S3C2410_TCON_T2MANUALUPD; tmp1 = (readl(S3C2410_TCON) | S3C2410_TCON_T2RELOAD) & (~S3C2410_TCON_T2MANUALUPD); writel(tmp, S3C2410_TCON); if(pwm->off) writel(tmp1 & (~S3C2410_TCON_T2START), S3C2410_TCON); else writel(tmp1 | S3C2410_TCON_T2START, S3C2410_TCON); break; case 3: tmp = readl(S3C2410_TCFG1); tmp = (tmp & (~(0x0F<<12))) | ((pwm->div_clock&0x000F)<<12); writel(tmp, S3C2410_TCFG1); writel(pwm->tcntb_reg&0xFFFF, S3C2410_TCNTB(channel)); writel(pwm->tcmpb_reg&0xFFFF, S3C2410_TCMPB(channel)); tmp = readl(S3C2410_TCON) | S3C2410_TCON_T3RELOAD | S3C2410_TCON_T3MANUALUPD; tmp1 = (readl(S3C2410_TCON) | S3C2410_TCON_T3RELOAD) & (~S3C2410_TCON_T3MANUALUPD); writel(tmp, S3C2410_TCON); if(pwm->off) writel(tmp1 & (~S3C2410_TCON_T3START), S3C2410_TCON); else writel(tmp1 | S3C2410_TCON_T3START, S3C2410_TCON); break; default: break; } return 0;}static int pwm_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg){ struct PWM_CHANNEL pwm; switch(cmd) { case PWM_CHANNEL_0: case PWM_CHANNEL_1: case PWM_CHANNEL_2: case PWM_CHANNEL_3: if(copy_from_user(&pwm,(struct PWM_CHANNEL *)arg,sizeof(struct PWM_CHANNEL))) return -EFAULT; pwm_set_channel(cmd,&pwm); break; default: return -EFAULT; } return 0;}static int pwm_open(struct inode * inode, struct file * filp){ return 0;}static int pwm_release(struct inode * inode, struct file * filp){ return 0;}static struct file_operations pwm_fops = { .owner = THIS_MODULE, .ioctl = pwm_ioctl, .open = pwm_open, .release=pwm_release,}; static int __init pwm_init(void){ int ret; ret = register_chrdev(0,DEVICE_NAME,&pwm_fops); if(ret < 0) { printk("pwm: can't get major number\n"); return ret; } pwm_major = ret;#ifdef CONFIG_DEVFS_FS ret = devfs_mk_cdev(MKDEV(pwm_major,0), S_IFCHR | S_IRUGO | S_IWUSR,DEVICE_NAME); if(ret) { unregister_chrdev(pwm_major,DEVICE_NAME); printk("pwm: can't make char device fo devfs\n"); return ret; }#endif s3c2410_gpio_cfgpin(S3C2410_GPB0,S3C2410_GPB0_TOUT0); s3c2410_gpio_cfgpin(S3C2410_GPB1,S3C2410_GPB1_TOUT1); s3c2410_gpio_cfgpin(S3C2410_GPB2,S3C2410_GPB2_TOUT2); s3c2410_gpio_cfgpin(S3C2410_GPB3,S3C2410_GPB3_TOUT3); printk("s3c2410_pwm driver initial\n"); return 0;}static void __exit pwm_exit(void){#ifdef CONFIG_DEVFS_FS devfs_remove(DEVICE_NAME);#endif unregister_chrdev(pwm_major,DEVICE_NAME); printk("s3c2410_pwm driver removed\n"); }module_init(pwm_init);module_exit(pwm_exit);MODULE_ALIAS("pwm"); MODULE_DESCRIPTION("PWM IO Driver For EM104-MINI2410");MODULE_AUTHOR("LIANXJ");MODULE_LICENSE("GPL");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -