您的位置:首页 > 编程语言

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

2013-10-08 10:21 447 查看
#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");
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: