iTop4412驱动开发之八:PWM方式蜂鸣器驱动

    技术2024-07-25  13

    #include <linux/init.h> #include <linux/module.h> #include <linux/cdev.h> #include <linux/types.h> #include <linux/fs.h> #include <linux/errno.h> #include <linux/mm.h> #include <asm/io.h> #include <asm/system.h> #include <asm/uaccess.h> #include <linux/slab.h> #include <linux/delay.h> #include <linux/interrupt.h> #include <linux/gpio.h> #include <plat/gpio-cfg.h> #include <mach/gpio.h> #include <mach/gpio-exynos4.h> #include <linux/platform_device.h> #include <mach/regs-gpio.h> #include <asm/io.h> #include <linux/regulator/consumer.h> #define DRIVER_NAME "pwm_beep" typedef struct { unsigned int TCFG0; unsigned int TCFG1; unsigned int TCON; unsigned int TCNTB0; unsigned int TCMPB0; unsigned int TCNTO0; unsigned int TCNTB1; unsigned int TCMPB1; unsigned int TCNTO1; unsigned int TCNTB2; unsigned int TCMPB2; unsigned int TCNTO2; unsigned int TCNTB3; unsigned int TCMPB3; unsigned int TCNTO3; unsigned int TCNTB4; unsigned int TCMPB4; unsigned int TCNTO4; unsigned int TINT_CSTAT; } PWM_Register; PWM_Register *pwm_virt_addr = NULL; volatile unsigned long pwm_phys_addr; volatile unsigned long *GPL2CON, *GPL2DAT, *GPL2PUD; struct resource *ioresource = NULL; void pwm_init(void) { //PWM物理地址映射到虚拟地址 pwm_phys_addr = 0x139D0000; pwm_virt_addr = (PWM_Register*)(unsigned long)ioremap(pwm_phys_addr, 0x44); //初始化寄存器 pwm_virt_addr->TCFG0 &= ~0xff; //低4位清零 pwm_virt_addr->TCFG0 |= 0xff; //预分步255 pwm_virt_addr->TCFG1 &= ~0xf; //低4位清零 pwm_virt_addr->TCFG1 |= 0x4; //1/16分频 //设置计算器,比较寄存器值,根据手册说明,设置预分频255,分频1/16时,约每1秒翻转一次 pwm_virt_addr->TCNTB0 = 32000; pwm_virt_addr->TCMPB0 = 16000; //先手动装载一次计数 pwm_virt_addr->TCON &= ~0xf; //低4位清零 pwm_virt_addr->TCON |= 0x3; } void beep_on() { //再开启自动装载 if (pwm_virt_addr) { pwm_virt_addr->TCON &= ~0xf; //低4位清零 pwm_virt_addr->TCON |= 0x8 | 0x1; } } void beep_off() { if (pwm_virt_addr) { pwm_virt_addr->TCON &= ~0x8; pwm_virt_addr->TCON &= ~0x1; } } int pwm_beep_open(struct inode *inode,struct file *filp) { DPRINTK("Device Opened Success!\n"); beep_on(); return nonseekable_open(inode,filp); } int pwm_beep_release(struct inode *inode,struct file *filp) { DPRINTK("Device Closed Success!\n"); beep_off(); return 0; } long pwm_beep_ioctl(struct file *filp,unsigned int cmd,unsigned long arg) { return 0; } static struct file_operations beep_ops = { .owner = THIS_MODULE, .open = pwm_beep_open, .release= pwm_beep_release, .unlocked_ioctl = pwm_beep_ioctl, }; static struct miscdevice beep_dev = { .minor = MISC_DYNAMIC_MINOR, .fops = &beep_ops, .name = "pwm_beep", }; static int pwm_beep_probe(struct platform_device *pdev) { int ret, i; char *banner = "pwm_beep_test init.\n"; printk(banner); //初始化BEEP控制GPIO ret = gpio_request(EXYNOS4_GPD0(0), "BEEP"); if (ret) { printk("gpio request gpd0 failed.\n"); return 0; } //设备GPD0_0为PWM输出模式 s3c_gpio_cfgpin(EXYNOS4_GPD0(0), S3C_GPIO_SFN(0x2)); s3c_gpio_setpull(EXYNOS4_GPD0(0), S3C_GPIO_PULL_NONE); gpio_free(EXYNOS4_GPD0(0)); //初始化PWM0寄存器 pwm_init(); ret = misc_register(&beep_dev); if(ret<0) { printk("pwm beep: register misc device failed!\n"); return -1; } return 0; } static int pwm_beep_remove(struct platform_device *pdev) { beep_off(); if (pwm_phys_addr) iounmap(pwm_phys_addr); return 0; } static struct platform_driver pwm_beep_driver = { .probe = pwm_beep_probe, .remove = pwm_beep_remove, .driver = { .name = DRIVER_NAME, .owner = THIS_MODULE, } }; struct platform_device pwm_beep_dev = { .name = "pwm_beep", .id = -1, }; static int __init pwm_beep_init(void) { platform_device_register(&pwm_beep_dev); platform_driver_register(&pwm_beep_driver); return 0; } static void __exit pwm_beep_exit(void) { platform_driver_unregister(&pwm_beep_driver); platform_device_unregister(&pwm_beep_dev); } module_init(pwm_beep_init); module_exit(pwm_beep_exit); MODULE_LICENSE("Dual BSD/GPL");
    Processed: 0.014, SQL: 9