권남 2015. 6. 3. 17:54
001: #include <linux/miscdevice.h>
002: #include <linux/init.h>
003: #include <linux/module.h>
004: #include <linux/kernel.h>
005: #include <linux/fs.h>
006: #include <linux/types.h>
007: #include <linux/delay.h>
008: #include <linux/ioport.h>
009: #include <asm/uaccess.h>
010: #include <mach/gpio.h>
011: #include <plat/gpio-cfg.h>
012: #include <linux/pwm.h>
013: #include <linux/delay.h>
014:
015: #define PIEZO_PWM_CH 2
016: #define PERIOD_NS 38265        /* 1000000000 / 35714 => 28 Khz //38265 => 30Khz*/
017: #define DUTY_NS 1000*18       /* 1000(1 us) * 18 => 18 us */
018:
019: static struct pwm_device *piezo_pwm;
020: static unsigned int piezo_period_ns;

021: static unsigned int piezo_duty_ns;
023: static int period_table[] =
024: {
025:   956022, 902527, 851788, 803858,
026:   758725, 716332, 676132, 638162,
027:   602046, 568181, 536480, 506329,
028:   477783, 451059, 425713, 401767,
029:   379218, 358037, 337952, 318979,
030:   301023, 284090, 268168, 253100
031: };
032:
033: #define DRIVER_AUTHOR  "hanback"       
034: #define DRIVER_DESC  "m2 piezo driver"
035: #define  PIEZO_NAME  "m2_piezo" 
036:
037: #define PIEZO_MAJOR  240
038:
039: static int piezo_open( struct inode* inode, struct file* file)
040: {
041:   int err=0;
042:  
043:   err = gpio_request(EXYNOS4_GPD0(2),"GPD0");
044:   if(err)
045:     printk("piezo.c failed to request GPD0(2)\n");
046:   s3c_gpio_cfgpin(EXYNOS4_GPD0(2),S3C_GPIO_SFN(2));
047:
048:   piezo_period_ns = PERIOD_NS;
049:   piezo_duty_ns = DUTY_NS;

050:   piezo_pwm = pwm_request(PIEZO_PWM_CH,"piezo");051:   if(IS_ERR(piezo_pwm))
052:   {
053:     printk(KERN_ERR "unable to request PWM for PIEZO\n");
054:     return PTR_ERR(piezo_pwm);
055:   }
056:   return 0;
057: }
058:
059: static int piezo_release( struct inode* inode, struct file* file)
060: {
061:   pwm_config(piezo_pwm,0,piezo_period_ns);
062:   pwm_disable(piezo_pwm);
063:   pwm_free(piezo_pwm);
064:   return 0;
065: }
066:
067: static ssize_t piezo_write( struct file *filp, const char *buf, size_t length, loff_t *ofs )
068: {
069:   int period;
070:   int ret;
071:   ret = copy_from_user(&period,buf,length);
072:   pwm_config(piezo_pwm,piezo_duty_ns,period_table[period]);
073:   pwm_enable(piezo_pwm);
074:   mdelay(500);
075:   pwm_config(piezo_pwm,0,piezo_period_ns);
076:   return 0;
077: }

079: static struct file_operations piezo_fops =
080: {
081:         .owner = THIS_MODULE,
082:         .open = piezo_open,
083:         .release = piezo_release,
084:         .write = piezo_write,
085: };
086:
087: static struct miscdevice piezo_driver =
088: {
089:         .minor = MISC_DYNAMIC_MINOR,
090:         .name = PIEZO_NAME,
091:         .fops = &piezo_fops,
092: };
093:
094: int piezo_init(void)
095: {
096:   printk("driver : %s DRIVER INIT\n",PIEZO_NAME);
097:   return misc_register(&piezo_driver);
098: }
099:
100: void piezo_exit(void)
101: {
102:   misc_deregister(&piezo_driver);
103:   printk("driver: %s DRIVER EXIT\n", PIEZO_NAME);
104: }
105:
106: module_init(piezo_init); 

107: module_exit(piezo_exit);  
109: MODULE_AUTHOR(DRIVER_AUTHOR); 
110: MODULE_DESCRIPTION(DRIVER_DESC);

111: MODULE_LICENSE("Dual BSD/GPL");