tiny6410PWM驱动注释

  1 #include <linux/module.h>
  2 #include <linux/kernel.h>
  3 #include <linux/fs.h>
  4 #include <linux/init.h>
  5 #include <linux/delay.h>
  6 #include <linux/poll.h>
  7 #include <asm/irq.h>
  8 #include <asm/io.h>//linux对IO操作的定义 
  9 #include <linux/interrupt.h>
 10 #include <asm/uaccess.h>
 11 #include <mach/hardware.h>
 12 #include <plat/regs-timer.h> //定义了平台相关的PWM 定时器的寄存器宏
 13 #include <mach/regs-irq.h>
 14 #include <asm/mach/time.h>
 15 #include <linux/clk.h>
 16 #include <linux/cdev.h>
 17 #include <linux/device.h>
 18 #include <linux/miscdevice.h>
 19 
 20 #include <mach/map.h>
 21 #include <mach/regs-clock.h>
 22 #include <mach/regs-gpio.h>
 23 
 24 #include <plat/gpio-cfg.h>
 25 #include <mach/gpio-bank-e.h>
 26 #include <mach/gpio-bank-f.h>
 27 #include <mach/gpio-bank-k.h>
 28 
 29 #define DEVICE_NAME     "pwm" //设备名称
 30 
 31 //下面两个宏是作为ioctl的cmd使用的
 32 #define PWM_IOCTL_SET_FREQ        1
 33 #define PWM_IOCTL_STOP            0
 34 
 35 //这里定义一个信号量
 36 static struct semaphore lock;
 37 
 38 /* freq:  pclk/50/16/65536 ~ pclk/50/16 
 39   * if pclk = 50MHz, freq is 1Hz to 62500Hz
 40   * human ear : 20Hz~ 20000Hz
 41   */
 42 static void PWM_Set_Freq( unsigned long freq )
 43 {
 44     unsigned long tcon;
 45     unsigned long tcnt;
 46     unsigned long tcfg1;
 47     unsigned long tcfg0;
 48 
 49     struct clk *clk_p;
 50     unsigned long pclk;
 51 
 52     unsigned tmp;
 53 
 54     tmp = readl(S3C64XX_GPFCON);//读取模式设定寄存器值
 55     tmp &= ~(0x3U << 28);//GPF14脚清0
 56     tmp |=  (0x2U << 28);//设置为10模式 即 PWM TOUT模式
 57     writel(tmp, S3C64XX_GPFCON);//写配置
 58 
 59     tcon = __raw_readl(S3C_TCON);//读取定时器配置寄存器
 60     tcfg1 = __raw_readl(S3C_TCFG1);//控制DMA
 61     tcfg0 = __raw_readl(S3C_TCFG0);//控制分频和死区
 62 
 63     //prescaler = 50
 64     tcfg0 &= ~S3C_TCFG_PRESCALER0_MASK;
 65     tcfg0 |= (50 - 1); 
 66 
 67     //mux = 1/16
 68     tcfg1 &= ~S3C_TCFG1_MUX0_MASK;
 69     tcfg1 |= S3C_TCFG1_MUX0_DIV16;
 70 
 71     __raw_writel(tcfg1, S3C_TCFG1);
 72     __raw_writel(tcfg0, S3C_TCFG0);
 73 
 74     clk_p = clk_get(NULL, "pclk");//获取pclk时钟频率
 75     pclk  = clk_get_rate(clk_p);//得到频率信息
 76     tcnt  = (pclk/50/16)/freq;//得到定时器值
 77     
 78     __raw_writel(tcnt, S3C_TCNTB(0));
 79     __raw_writel(tcnt/2, S3C_TCMPB(0));//50%占空比
 80                 
 81     tcon &= ~0x1f;
 82     tcon |= 0xb;        //disable deadzone, auto-reload, inv-off, update TCNTB0&TCMPB0, start timer 0
 83     __raw_writel(tcon, S3C_TCON);
 84     
 85     tcon &= ~2;            //clear manual update bit
 86     __raw_writel(tcon, S3C_TCON);
 87 }
 88 
 89 void PWM_Stop( void )
 90 {
 91     unsigned tmp;
 92     tmp = readl(S3C64XX_GPFCON);
 93     tmp &= ~(0x3U << 28); //清0代表设置为输入
 94     writel(tmp, S3C64XX_GPFCON);
 95 }
 96 
 97 static int s3c64xx_pwm_open(struct inode *inode, struct file *file)
 98 {
 99     if (!down_trylock(&lock))//如果没有获得信号量 则进程进入休眠态
100         return 0;
101     else
102         return -EBUSY;
103 }
104 
105 
106 static int s3c64xx_pwm_close(struct inode *inode, struct file *file)
107 {
108     up(&lock);//释放信号量
109     return 0;
110 }
111 
112 
113 static long s3c64xx_pwm_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
114 {
115     switch (cmd) {
116         case PWM_IOCTL_SET_FREQ:
117             if (arg == 0)
118                 return -EINVAL;
119             PWM_Set_Freq(arg);
120             break;
121 
122         case PWM_IOCTL_STOP:
123         default:
124             PWM_Stop();
125             break;
126     }
127 
128     return 0;
129 }
130 
131 
132 static struct file_operations dev_fops = {
133     .owner            = THIS_MODULE,
134     .open            = s3c64xx_pwm_open,
135     .release        = s3c64xx_pwm_close, 
136     .unlocked_ioctl    = s3c64xx_pwm_ioctl,
137 };
138 
139 //仍然定义为杂项设备
140 static struct miscdevice misc = {
141     .minor = MISC_DYNAMIC_MINOR,
142     .name = DEVICE_NAME,
143     .fops = &dev_fops,
144 };
145 
146 static int __init dev_init(void)
147 {
148     int ret;
149 
150     sema_init(&lock, 1);//初始化一个互斥信号量 设备初始化的时候便会一直存在
151     ret = misc_register(&misc);//注册设备
152 
153     printk (DEVICE_NAME"\tinitialized\n");
154         return ret;
155 }
156 
157 static void __exit dev_exit(void)
158 {
159     misc_deregister(&misc);
160 }
161 
162 module_init(dev_init);
163 module_exit(dev_exit);
164 MODULE_LICENSE("GPL");
165 MODULE_AUTHOR("FriendlyARM Inc.");
166 MODULE_DESCRIPTION("S3C6410 PWM Driver");

 

posted @ 2019-06-12 10:31  robinjr  阅读(194)  评论(0)    收藏  举报