ARM11 硬件 PWM驱动蜂鸣器设备代码

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/poll.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <linux/interrupt.h>
#include <asm/uaccess.h>
#include <mach/hardware.h>
#include <plat/regs-timer.h>
#include <mach/regs-irq.h>
#include <asm/mach/time.h>
#include <linux/clk.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/miscdevice.h>

#include <mach/map.h>
#include <mach/regs-clock.h>
#include <mach/regs-gpio.h>

#include <plat/gpio-cfg.h>
#include <mach/gpio.h>
#include <mach/gpio-bank-f.h>

#define device_name "misc_pwm"

#define command_set_freq 0
#define command_stop 1

static struct semaphore flag;

static void PWM_set_freq(unsigned long freq)
{
 unsigned long tcon;
 unsigned long tcnt;
 unsigned long tcfg0;
 unsigned long tcfg1; 

 struct clk *clk_pointer;
 unsigned long pclk;
 
 s3c_gpio_cfgpin(S3C64XX_GPF(14),S3C64XX_GPF14_PWM_TOUT0);
 
 tcon = __raw_readl(S3C_TCON);
 tcfg0 = __raw_readl(S3C_TCFG0);
 tcfg1 = __raw_readl(S3C_TCFG1);

 tcfg0 &= ~(S3C_TCFG_PRESCALER0_MASK);
 tcfg0 |= 1;
 __raw_writel(tcfg0,S3C_TCFG0);

 tcfg1 &= ~(S3C_TCFG1_MUX0_MASK);
 tcfg1 |= S3C_TCFG1_MUX0_DIV1;
 __raw_writel(tcfg1,S3C_TCFG1);

 clk_pointer = clk_get(NULL,"pclk");
 pclk = clk_get_rate(clk_pointer);
 tcnt = (pclk/1/1)/freq;

 __raw_writel(tcnt, S3C_TCNTB(0));
 __raw_writel(tcnt/2, S3C_TCMPB(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)
{
 s3c_gpio_cfgpin(S3C64XX_GPF(14),S3C_GPIO_INPUT);
 __raw_writel(0x00,S3C_TCON);
}

static int PWM_open(struct inode *inode, struct file *filp)
{
 if(!down_trylock(&flag))
 {
  return 0;
 }
 else
 {
  return -EBUSY;
 }
}

static int PWM_release(struct inode *inode,struct file *filp)
{
 up(&flag);
 
 return 0;
}

static long PWM_unlocked_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
 switch(cmd)
 {
  case command_set_freq:
   PWM_set_freq(arg);
   break;
  case command_stop:
   PWM_Stop();
   break;
  default:  
   PWM_Stop();
   break;
 }
 return 0;
}

static struct file_operations PWM_fops = {
 .owner = THIS_MODULE,
 .open = PWM_open,
 .release = PWM_release,
 .unlocked_ioctl = PWM_unlocked_ioctl,
};

static struct miscdevice miscpwm = {
 .minor = MISC_DYNAMIC_MINOR,
 .name = device_name,
 .fops = &PWM_fops,
};

int pwm_up_init(void)
{
 int ret;
 
 sema_init(&flag,1);
 ret = misc_register(&miscpwm);

 if(ret < 0)
 {
  printk("the pwm has unmodule \n");
 }
 printk("the pwm has registered \n");

 return 0;
}

void pwm_exit(void)
{
 misc_deregister(&miscpwm);
 printk("the pwm has exit\n");
}

module_init(pwm_up_init);
module_exit(pwm_exit);

MODULE_LICENSE("GPL");

 

 

 

 


 

你可能感兴趣的:(linux,单片机,ARM11,6410)