?? 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);
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("FENG");
MODULE_LICENSE("GPL");
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -