- #include
<</SPAN>linux/module.h> - #include
<</SPAN>linux/kernel.h> - #include
<</SPAN>linux/fs.h> - #include
<</SPAN>linux/init.h> - #include
<</SPAN>linux/delay.h> - #include
<</SPAN>linux/poll.h> - #include
<</SPAN>asm/irq.h> - #include
<</SPAN>asm/io.h> - #include
<</SPAN>linux/interrupt.h> - #include
<</SPAN>asm/uaccess.h> - #include
<</SPAN>mach/hardware.h> - #include
<</SPAN>plat/regs-timer.h> - #include
<</SPAN>mach/regs-irq.h> - #include
<</SPAN>asm/mach/time.h> - #include
<</SPAN>linux/clk.h> - #include
<</SPAN>linux/cdev.h> - #include
<</SPAN>linux/device.h> - #include
<</SPAN>linux/miscdevice.h> -
- #include
<</SPAN>mach/map.h> - #include
<</SPAN>mach/regs-clock.h> - #include
<</SPAN>mach/regs-gpio.h> -
- #include
<</SPAN>plat/gpio-cfg.h> - #include
<</SPAN>mach/gpio-bank-e.h> - #include
<</SPAN>mach/gpio-bank-f.h> - #include
<</SPAN>mach/gpio-bank-k.h> -
- #define
DEVICE_NAME "pwm" -
- #define
PWM_IOCTL_SET_FREQ 1 - #define
PWM_IOCTL_STOP 0 -
- static
struct semaphore lock; //信号量 -
-
- static
void PWM_Set_Freq( unsigned long freq ) - {
-
unsigned long tcon; -
unsigned long tcnt; -
unsigned long tcfg1; -
unsigned long tcfg0; -
-
struct clk *clk_p; -
unsigned long pclk; -
-
unsigned tmp; -
-
tmp = readl(S3C64XX_GPFCON); -
//tmp &= ~(0x3U <</SPAN><</SPAN> 28); -
//tmp |= (0x2U <</SPAN><</SPAN> 28); -
-
tmp &=~(0x3U <</SPAN><</SPAN> 30); //GPF15 [31:30] 10 = PWM TOUT[1] -
tmp |= (0x2U <</SPAN><</SPAN> 30); -
-
writel(tmp, S3C64XX_GPFCON); -
-
tcon = __raw_readl(S3C_TCON); //定时器控制寄存器 -
tcfg1 = __raw_readl(S3C_TCFG1); //时钟多路复用器和 DMA模式的选择 -
tcfg0 = __raw_readl(S3C_TCFG0); //时钟预定标器和死区结构 -
-
//prescaler = 50 Prescaler 0 [7:0] R/W Prescaler 0 value for timer 0 & 1 -
tcfg0 &= ~S3C_TCFG_PRESCALER0_MASK; //{prescaler value} = 1~255 -
tcfg0 |= (50 - 1); //prescaler value=50 -
-
//mux = 1/16 TCFG1 Divider MUX0 [3:0] R/W Select Mux input for PWM Timer 0 -
tcfg1 &= ~S3C_TCFG1_MUX0_MASK; -
tcfg1 |= S3C_TCFG1_MUX0_DIV16; // 0100: 1/16 -
-
__raw_writel(tcfg1, S3C_TCFG1); -
__raw_writel(tcfg0, S3C_TCFG0); -
-
-
-
-
-
clk_p = clk_get(NULL, "pclk"); //获取一个名为id的时针 -
pclk = clk_get_rate(clk_p); //获取该时钟的频率 -
//定时器输入时钟频率 -
//Timer input clock Frequency = PCLK / ( {prescaler value + 1} ) / {divider value} -
tcnt = (pclk/50/16)/freq; -
-
__raw_writel(tcnt, S3C_TCNTB(0)); //TCNTB0:定时器0计数缓冲器。 -
__raw_writel(tcnt/2, S3C_TCMPB(0));//TCMPB0:定时器0比较缓冲寄存器。 -
-
tcon &= ~0x1f; -
tcon |= 0xb; //disable deadzone, auto-reload, inv-off, update TCNTB0&TCMPB0, start timer 0 -
__raw_writel(tcon, S3C_TCON); -
-
-
-
tcon &= ~2; //clear manual update bit -
__raw_writel(tcon, S3C_TCON); - }
-
- void
PWM_Stop( void ) - {
-
unsigned tmp; -
tmp = readl(S3C64XX_GPFCON); -
//tmp &= ~(0x3U <</SPAN><</SPAN> 28); -
tmp &= ~(0x3U <</SPAN><</SPAN> 30); -
-
writel(tmp, S3C64XX_GPFCON); - }
-
-
- static
int s3c64xx_pwm_open(struct inode *inode, struct file *file) - {
-
if (!down_trylock(&lock)) -
return 0; -
else -
return -EBUSY; - }
-
-
- static
int s3c64xx_pwm_close(struct inode *inode, struct file *file) - {
-
up(&lock); //该函数释放信号量sem,唤醒等待者 -
return 0; - }
-
-
- static
long s3c64xx_pwm_ioctl(struct file *filep, unsigned int cmd, unsigned long arg) - {
-
switch (cmd) { -
case PWM_IOCTL_SET_FREQ: -
if (arg == 0) -
return -EINVAL; -
PWM_Set_Freq(arg); -
break; -
-
case PWM_IOCTL_STOP: -
default: -
PWM_Stop(); -
break; -
} -
-
return 0; - }
-
-
- static
struct file_operations dev_fops = { -
.owner = THIS_MODULE, -
.open = s3c64xx_pwm_open, -
.release = s3c64xx_pwm_close, -
.unlocked_ioctl = s3c64xx_pwm_ioctl, - };
-
- static
struct miscdevice misc = { -
.minor = MISC_DYNAMIC_MINOR, -
.name = DEVICE_NAME, -
.fops = &dev_fops, - };
-
- static
int __init dev_init(void) - {
-
int ret; -
-
-
init_MUTEX(&lock); -
ret = misc_register(&misc); -
-
printk (DEVICE_NAME"\tinitialized\n"); -
return ret; - }
-
- static
void __exit dev_exit(void) - {
-
misc_deregister(&misc); - }
-
- module_init(dev_init);
- module_exit(dev_exit);
- MODULE_LICENSE("GPL");
- MODULE_AUTHOR("FORLINX
Inc."); - MODULE_DESCRIPTION("S3C6410
PWM Driver");
OK6410 PWM波形输出代码
最新推荐文章于 2023-01-05 17:06:23 发布