diff options
author | Srikant Patnaik | 2015-01-11 12:28:04 +0530 |
---|---|---|
committer | Srikant Patnaik | 2015-01-11 12:28:04 +0530 |
commit | 871480933a1c28f8a9fed4c4d34d06c439a7a422 (patch) | |
tree | 8718f573808810c2a1e8cb8fb6ac469093ca2784 /drivers/char/wmt-pwm.c | |
parent | 9d40ac5867b9aefe0722bc1f110b965ff294d30d (diff) | |
download | FOSSEE-netbook-kernel-source-871480933a1c28f8a9fed4c4d34d06c439a7a422.tar.gz FOSSEE-netbook-kernel-source-871480933a1c28f8a9fed4c4d34d06c439a7a422.tar.bz2 FOSSEE-netbook-kernel-source-871480933a1c28f8a9fed4c4d34d06c439a7a422.zip |
Moved, renamed, and deleted files
The original directory structure was scattered and unorganized.
Changes are basically to make it look like kernel structure.
Diffstat (limited to 'drivers/char/wmt-pwm.c')
-rwxr-xr-x | drivers/char/wmt-pwm.c | 830 |
1 files changed, 830 insertions, 0 deletions
diff --git a/drivers/char/wmt-pwm.c b/drivers/char/wmt-pwm.c new file mode 100755 index 00000000..fd9809b6 --- /dev/null +++ b/drivers/char/wmt-pwm.c @@ -0,0 +1,830 @@ +/*++ +linux/drivers/char/wmt-pwm.c + +Copyright (c) 2008 WonderMedia Technologies, Inc. + +This program is free software: you can redistribute it and/or modify it under the +terms of the GNU General Public License as published by the Free Software Foundation, +either version 2 of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. See the GNU General Public License for more details. +You should have received a copy of the GNU General Public License along with +this program. If not, see <http://www.gnu.org/licenses/>. + +WonderMedia Technologies, Inc. +10F, 529, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C. +--*/ + +#define WMT_PWM_C + +/*--- wmt-pwm.c --------------------------------------------------------------- +* Copyright (C) 2009 WMT Tech. Inc. +* +* MODULE : wmt-pwm.c +* AUTHOR : Sam Shen +* DATE : 2009/8/12 +* DESCRIPTION : +*-----------------------------------------------------------------------------*/ + +/*--- History ------------------------------------------------------------------- +*Version 0.01 , Sam Shen, 2009/8/12 +* First version +* +*------------------------------------------------------------------------------*/ + +#include <linux/init.h> +#include <linux/module.h> +#include <linux/types.h> +#include <linux/fs.h> +#include <linux/kernel.h> +#include <linux/platform_device.h> +#include <linux/errno.h> +#include <asm/uaccess.h> +#include <linux/kdev_t.h> +#include <linux/cdev.h> +#include <linux/proc_fs.h> +#include <linux/jiffies.h> +#include <linux/major.h> +#include <linux/delay.h> +#include <linux/sysctl.h> + +#include "wmt-pwm.h" + +// #define DEBUG + +#ifdef __KERNEL__ +#define DPRINT printk +#else +#define DPRINT printf +#endif + +#ifdef DEBUG +#define DBG(fmt, args...) DPRINT("[BTM] %s: " fmt, __FUNCTION__ , ## args) +#define DBG_DETAIL(fmt, args...) DPRINT("[BTM] %s: " fmt, __FUNCTION__ , ## args) +#else +#define DBG(fmt, args...) +#define DBG_DETAIL(fmt, args...) +#endif + +#define DEVICE_NAME "WMT-PWM" +#define PWM_NUM 2 /* WM3429 has 2 pwm outputs */ + +struct pwm_dev_s { + /* module parameters */ + + /* char dev struct */ + struct cdev cdev; +}; +#define PWM_MAJOR 239 +static int pwm_dev_major = PWM_MAJOR; +static int pwm_dev_minor = 0; +static int pwm_dev_nr = 1; +static int pwm_dev_ref = 0; /* is device open */ +static struct pwm_dev_s pwm_dev; + +unsigned int pwm_level[2] = { 0, 0 }; +unsigned int pwm_freq[2] = {16000, 16000 }; //modified by howayhuo. org: {1000, 1000 } +static unsigned int pwm_enable[2] = {0,0}; + +DEFINE_SEMAPHORE(pwm_lock); + +#define ENV_DISPLAY_PWM "wmt.display.pwm" +#define ENV_LCD_POWER "wmt.gpo.lcd" +#define GPIO_PHY_BASE_ADDR (GPIO_BASE_ADDR-WMT_MMAP_OFFSET) + +struct gpio_operation_t { + unsigned int id; + unsigned int act; + unsigned int bitmap; + unsigned int ctl; + unsigned int oc; + unsigned int od; +}; +static struct gpio_operation_t g_lcd_pw_pin; +static int g_pwm_invert; +static int g_pwm_param; +static unsigned int g_pwm_power; + +extern int wmt_getsyspara(char *varname, unsigned char *varval, int *varlen); +extern void lcd_set_enable(int enable); + +void pwm_get_env(void) +{ + unsigned char buf[100]; + int varlen = 100; + g_pwm_invert = 0; + if( wmt_getsyspara(ENV_DISPLAY_PWM,buf,&varlen) == 0) { + //printk(" pwm_get_env : %s = %s \n",ENV_DISPLAY_PWM,buf); + sscanf(buf,"%x",&g_pwm_invert); + //sscanf(buf,"%d",&g_pwm_invert); + g_pwm_invert = (g_pwm_invert&0xFF); + g_pwm_invert = g_pwm_invert >> 4; + } + memset(&g_lcd_pw_pin, 0, sizeof(struct gpio_operation_t)); + if( wmt_getsyspara(ENV_LCD_POWER,buf,&varlen) == 0) { + //printk(" pwm_get_env : %s = %s \n",ENV_LCD_POWER,buf); + sscanf(buf,"%x:%d:%x:%x:%x:%x",&g_lcd_pw_pin.id, &g_lcd_pw_pin.act, &g_lcd_pw_pin.bitmap, &g_lcd_pw_pin.ctl, \ + &g_lcd_pw_pin.oc, &g_lcd_pw_pin.od); + if ((g_lcd_pw_pin.ctl&0xffff0000) == GPIO_PHY_BASE_ADDR) + g_lcd_pw_pin.ctl += WMT_MMAP_OFFSET; + if ((g_lcd_pw_pin.oc&0xffff0000) == GPIO_PHY_BASE_ADDR) + g_lcd_pw_pin.oc += WMT_MMAP_OFFSET; + if ((g_lcd_pw_pin.od&0xffff0000) == GPIO_PHY_BASE_ADDR) + g_lcd_pw_pin.od += WMT_MMAP_OFFSET; + } + g_pwm_param = 1; +} + +#define pwm_write_reg(addr,val,wait) \ + REG32_VAL(addr) = val; \ + while(REG32_VAL(PWM_STS_REG_ADDR)&=wait); + +void pwm_set_control(int no,unsigned int ctrl) +{ + unsigned int addr; + + addr = PWM_CTRL_REG_ADDR + (0x10 * no); + pwm_write_reg(addr,ctrl,PWM_CTRL_UPDATE << (8*no)); +} /* End of pwm_proc */ + +void pwm_set_scalar(int no,unsigned int scalar) +{ + unsigned int addr; + + addr = PWM_SCALAR_REG_ADDR + (0x10 * no); + pwm_write_reg(addr,scalar,PWM_SCALAR_UPDATE << (8*no)); +} + +void pwm_set_period(int no,unsigned int period) +{ + unsigned int addr; + + addr = PWM_PERIOD_REG_ADDR + (0x10 * no); + pwm_write_reg(addr,period,PWM_PERIOD_UPDATE << (8*no)); +} + +void pwm_set_duty(int no,unsigned int duty) +{ + unsigned int addr; + + addr = PWM_DUTY_REG_ADDR + (0x10 * no); + pwm_write_reg(addr,duty,PWM_DUTY_UPDATE << (8*no)); +} + +unsigned int pwm_get_period(int no) +{ + unsigned int addr; + + addr = PWM_PERIOD_REG_ADDR + (0x10 * no); + return (REG32_VAL(addr) & 0xFFF); +} + +unsigned int pwm_get_duty(int no) +{ + unsigned int addr; + + addr = PWM_DUTY_REG_ADDR + (0x10 * no); + return (REG32_VAL(addr) & 0xFFF); +} + +unsigned int get_lcd_power(void) +{ + return g_pwm_power; +/* + unsigned int val, reg; + + if ((g_lcd_pw_pin.ctl == 0) || (g_lcd_pw_pin.oc == 0) || (g_lcd_pw_pin.od == 0)) { + printk("lcd power ping not define\n"); + return 0; + } + val = 1<<g_lcd_pw_pin.bitmap; + reg = 0; + reg = REG32_VAL(g_lcd_pw_pin.ctl); + if (!(reg&val)) + return 0; + reg = REG32_VAL(g_lcd_pw_pin.oc); + if (!(reg&val)) + return 0; + reg = REG32_VAL(g_lcd_pw_pin.od); + reg = (reg&val); + if (g_lcd_pw_pin.act) { + if (reg) + return 1; + } else { + if (!reg) + return 1; + } + return 0; +*/ +} + +void set_lcd_power(int on) +{ + unsigned int val; + + if ((g_lcd_pw_pin.ctl == 0) || (g_lcd_pw_pin.oc == 0) || (g_lcd_pw_pin.od == 0)) { + printk("lcd power ping not define\n"); + return; + } + + val = 1<<g_lcd_pw_pin.bitmap; + if (g_lcd_pw_pin.act == 0) + on = ~on; + + if (on) { + REG32_VAL(g_lcd_pw_pin.od) |= val; + } else { + REG32_VAL(g_lcd_pw_pin.od) &= ~val; + } + REG32_VAL(g_lcd_pw_pin.ctl) |= val; + REG32_VAL(g_lcd_pw_pin.oc) |= val; + //printk("ctl = %x , oc = %x , od = %x\n",REG32_VAL(g_lcd_pw_pin.ctl),REG32_VAL(g_lcd_pw_pin.oc),REG32_VAL(g_lcd_pw_pin.od)); + +} +void pwm_set_gpio(int no,int enable) +{ + unsigned int pwm_pin; + + if( enable ) { + REG8_VAL(GPIO_OD_GP20_PWM0_BYTE_ADDR) &= 0xFE; + REG8_VAL(GPIO_CTRL_GP20_PWM0_BYTE_ADDR) &= 0xFE; + } else { + REG8_VAL(GPIO_OD_GP20_PWM0_BYTE_ADDR) &= 0xFE; + REG8_VAL(GPIO_OC_GP20_PWM0_BYTE_ADDR) |= 0x01; + REG8_VAL(GPIO_CTRL_GP20_PWM0_BYTE_ADDR) |= 0x01; + } + /* set to PWM mode */ + if ( no == 0 ) + REG32_VAL(PIN_SHARING_SEL_4BYTE_ADDR) &= ~0x1000; + else if( no == 1 ) + REG32_VAL(PIN_SHARING_SEL_4BYTE_ADDR) &= ~0x80; + g_pwm_power = (unsigned int)enable; + //lcd_set_enable(enable); + /*set_lcd_power(enable);*/ + +} + +void pwm_set_enable(int no,int enable) +{ + unsigned int addr,reg; + + if (g_pwm_param == 0) + pwm_get_env(); + pwm_enable[no] = enable; + addr = PWM_CTRL_REG_ADDR + (0x10 * no); + reg = REG32_VAL(addr); + if( enable ){ + reg |= PWM_ENABLE; + } + else { + reg &= ~PWM_ENABLE; + } + pwm_write_reg(addr,reg,PWM_CTRL_UPDATE << (4*no)); + pwm_set_gpio(no,enable); +} + +unsigned int pwm_get_enable(int no) +{ + unsigned int addr,reg; + + addr = PWM_CTRL_REG_ADDR + (0x10 * no); + reg = REG32_VAL(addr); + reg &= PWM_ENABLE; + return reg; +} + +void pwm_set_freq(int no,unsigned int freq) +{ + unsigned int clock; + unsigned int reg; + + auto_pll_divisor(DEV_PWM,CLK_ENABLE,0,0); + + pwm_freq[no] = freq; + + clock = auto_pll_divisor(DEV_PWM,GET_FREQ,0,0); + + reg = (clock / freq / PWM_PERIOD_VAL) -1; + pwm_set_scalar(no,reg); +} + +void pwm_set_level(int no,unsigned int level) +{ + unsigned int duty,period; + + auto_pll_divisor(DEV_PWM,CLK_ENABLE,0,0); + + if (g_pwm_param == 0) + pwm_get_env(); + pwm_level[no] = level; + period = PWM_PERIOD_VAL - 1; + duty = (level * PWM_PERIOD_VAL / 100); + duty = (duty)? (duty-1):0; + + pwm_set_period(no,period); + pwm_set_duty(no,duty); + if (g_pwm_invert) + pwm_set_control(no,(level)? 0x37:0x8); + else + pwm_set_control(no,(level)? 0x35:0x8); + pwm_set_gpio(no,level); +} + +void pwm_get_config(int no,unsigned int *freq,unsigned int *level) +{ + *freq = pwm_freq[no]; + *level = pwm_level[no]; +} + +#ifdef CONFIG_PROC_FS +static int pwm_do_freq0_proc(ctl_table * ctl,int write,void *buffer,size_t * len,loff_t *ppos) +{ + int ret = -1; + + ret = proc_dointvec(ctl, write, buffer, len, ppos); + if (write) + pwm_set_freq(0, pwm_freq[0]); + + return ret; +} + +static int pwm_do_freq1_proc(ctl_table * ctl,int write,void *buffer,size_t * len,loff_t *ppos) +{ + int ret = -1; + + ret = proc_dointvec(ctl, write, buffer, len, ppos); + if (write) + pwm_set_freq(1, pwm_freq[1]); + + return ret; +} + +static int pwm_do_level0_proc(ctl_table * ctl,int write,void *buffer,size_t * len,loff_t *ppos) +{ + int ret = -1; + + ret = proc_dointvec(ctl, write, buffer, len, ppos); + if (write) + pwm_set_level(0, pwm_level[0]); + + return ret; +} + +static int pwm_do_level1_proc(ctl_table * ctl,int write,void *buffer,size_t * len,loff_t *ppos) +{ + int ret = -1; + + ret = proc_dointvec(ctl, write, buffer, len, ppos); + if (write) + pwm_set_level(1, pwm_level[1]); + + return ret; +} + +static ctl_table pwm_table[] = { + { + .procname = "freq0", + .data = &pwm_freq[0], + .maxlen = sizeof(int), + .mode = 0666, + .proc_handler = &pwm_do_freq0_proc, + }, + { + .procname = "freq1", + .data = &pwm_freq[1], + .maxlen = sizeof(int), + .mode = 0666, + .proc_handler = &pwm_do_freq1_proc, + }, + { + .procname = "level0", + .data = &pwm_level[0], + .maxlen = sizeof(int), + .mode = 0666, + .proc_handler = &pwm_do_level0_proc, + }, + { + .procname = "level1", + .data = &pwm_level[1], + .maxlen = sizeof(int), + .mode = 0666, + .proc_handler = &pwm_do_level1_proc, + }, + { } +}; + +static ctl_table pwm_root_table[] = { + { + .procname = "pwm", // create path ==> /proc/sys/vpp + .mode = 0555, + .child = pwm_table + }, + { } +}; +static struct ctl_table_header *pwm_table_header; +#endif + +/*!************************************************************************* +* pwm_open() +* +* Private Function by Sam Shen, 2009/8/12 +*/ +/*! +* \brief +* +* \retval 0 if success +*/ +static int pwm_open +( + struct inode *inode, /*!<; //[IN] a pointer point to struct inode */ + struct file *filp /*!<; //[IN] a pointer point to struct file */ +) +{ + struct pwm_dev_s *dev; + int minor_no; + + DBG("Enter pwm_open\n"); + + if(pwm_dev_ref) + return -EBUSY; + + pwm_dev_ref++; + + try_module_get(THIS_MODULE); + + dev = container_of(inode->i_cdev,struct pwm_dev_s,cdev); + filp->private_data = dev; + minor_no = iminor(inode); /* get */ + + /* TODO */ + /* Step 1: check hardware resource */ + + /* Step 2: if first then initial hardware */ + + /* Step 3: update f_op pointer */ + + /* Step 4: allocate and assign provate_data structure */ + /* filp->private_data */ + + return 0; +} /* End of pwm_open() */ + +/*!************************************************************************* +* pwm_release() +* +* Private Function by Sam Shen, 2009/8/12 +*/ +/*! +* \brief +* +* \retval 0 if success +*/ +static int pwm_release +( + struct inode *inode, /*!<; //[IN] a pointer point to struct inode */ + struct file *filp /*!<; //[IN] a pointer point to struct file */ +) +{ + struct pwm_dev_s *dev; + + DBG("Enter pwm_release\n"); + + dev = container_of(inode->i_cdev,struct pwm_dev_s,cdev); + + pwm_dev_ref--; + module_put(THIS_MODULE); + + /* TODO */ + /* Step 1: free private data resource */ + + /* Step 2: if last then shutdown hardware */ + return 0; +} /* End of pwm_release() */ + +/*!************************************************************************* +* pwm_ioctl() +* +* Private Function by Sam Shen, 2009/8/12 +*/ +/*! +* \brief +* +* \retval 0 if success +*/ +static long pwm_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + int err = 0; + int retval = 0; + pwm_ctrl_t parm; + + /* check type and number, if fail return ENOTTY */ + if( _IOC_TYPE(cmd) != PWM_IOC_MAGIC ) return -ENOTTY; + if( _IOC_NR(cmd) >= PWM_IOC_MAXNR ) return -ENOTTY; + + /* check argument area */ + if( _IOC_DIR(cmd) & _IOC_READ ) + err = !access_ok( VERIFY_WRITE, (void __user *) arg, _IOC_SIZE(cmd)); + else if ( _IOC_DIR(cmd) & _IOC_WRITE ) + err = !access_ok( VERIFY_READ, (void __user *) arg, _IOC_SIZE(cmd)); + + if( err ) return -EFAULT; + + down(&pwm_lock); + + switch(cmd){ + case PWMIOSET_ENABLE: + copy_from_user( (void *) &parm, (const void *)arg, sizeof(pwm_ctrl_t)); + pwm_set_enable(parm.no,parm.value); + break; + case PWMIOSET_FREQ: + copy_from_user( (void *) &parm, (const void *)arg, sizeof(pwm_ctrl_t)); + pwm_freq[parm.no] = parm.value; + pwm_set_freq(parm.no,parm.value); + break; + case PWMIOGET_FREQ: + copy_from_user( (void *) &parm, (const void *)arg, sizeof(pwm_ctrl_t)); + parm.value = pwm_freq[parm.no]; + copy_to_user((void *) arg,(void *) &parm, sizeof(pwm_ctrl_t)); + break; + case PWMIOSET_LEVEL: + copy_from_user( (void *) &parm, (const void *)arg, sizeof(pwm_ctrl_t)); + pwm_level[parm.no] = parm.value; + pwm_set_level(parm.no,parm.value); + break; + case PWMIOGET_LEVEL: + copy_from_user( (void *) &parm, (const void *)arg, sizeof(pwm_ctrl_t)); + parm.value = pwm_level[parm.no]; + copy_to_user((void *) arg,(void *) &parm, sizeof(pwm_ctrl_t)); + break; + default: + retval = -ENOTTY; + break; + } + + up(&pwm_lock); + return retval; +} /* End of pwm_ioctl() */ + +/*!************************************************************************* + driver file operations struct define +****************************************************************************/ +struct file_operations pwm_fops = { + .owner = THIS_MODULE, + .open = pwm_open, + .unlocked_ioctl = pwm_ioctl, + .release = pwm_release, +}; + +/*!************************************************************************* +* pwm_probe() +* +* Private Function by Sam Shen, 2009/8/12 +*/ +/*! +* \brief +* +* \retval 0 if success +*/ +static int pwm_probe +( + struct platform_device *pdev /*!<; // please add parameters description her*/ +) +{ + int ret = 0; + dev_t dev_no; + struct cdev *cdev; + + dev_no = MKDEV(pwm_dev_major,pwm_dev_minor); + + /* register char device */ + // cdev = cdev_alloc(); + cdev = &pwm_dev.cdev; + cdev_init(cdev,&pwm_fops); + ret = cdev_add(cdev,dev_no,1); + + if( ret ){ + printk(KERN_ALERT "*E* register char dev \n"); + return ret; + } + +// printk( KERN_ALERT "/dev/%s major number %d, minor number %d\n", DEVICE_NAME, pwm_dev_major,pwm_dev_minor); + +#ifdef CONFIG_PROC_FS + pwm_table_header = register_sysctl_table(pwm_root_table); +#endif + return ret; +} /* End of pwm_probe() */ + +/*!************************************************************************* +* pwm_remove() +* +* Private Function by Sam Shen, 2009/8/12 +*/ +/*! +* \brief +* +* \retval 0 if success +*/ +static int pwm_remove +( + struct platform_device *dev /*!<; // please add parameters description her*/ +) +{ + struct cdev *cdev; + + cdev = &pwm_dev.cdev; + cdev_del(cdev); + printk( KERN_ALERT "Enter pwm_remove \n"); + return 0; +} /* End of pwm_remove() */ + +/*!************************************************************************* +* pwm_suspend() +* +* Private Function by Sam Shen, 2009/8/12 +*/ +/*! +* \brief +* +* \retval 0 if success +*/ +static int pwm_suspend +( + struct platform_device *pdev, /*!<; // a pointer point to struct device */ + pm_message_t state /*!<; // suspend state */ +) +{ +#ifndef CONFIG_ANDROID + int i; + for (i=0;i<PWM_NUM;i++) { + pwm_enable[i] = pwm_get_enable(i); + } +#endif + return 0; +} /* End of btm_suspend() */ + +/*!************************************************************************* +* pwm_resume() +* +* Private Function by Sam Shen, 2009/8/12 +*/ +/*! +* \brief +* +* \retval 0 if success +*/ +static int pwm_resume +( + struct platform_device *pdev /*!<; // a pointer point to struct device */ +) +{ +#ifndef CONFIG_ANDROID + int i; + for (i=0; i<PWM_NUM; i++) { + pwm_set_enable(i, pwm_enable[i]); + pwm_set_freq(i, pwm_freq[i]); + pwm_set_level(i, pwm_level[i]); + } +#endif + auto_pll_divisor(DEV_PWM,CLK_ENABLE,0,0); + return 0; +} /* End of pwm_resume() */ + +/*!************************************************************************* + device driver struct define +****************************************************************************/ +static struct platform_driver pwm_driver = { + .driver.name = "wmt-pwm", // This name should equal to platform device name. + .probe = pwm_probe, + .remove = pwm_remove, + .suspend = pwm_suspend, + .resume = pwm_resume +}; + +/*!************************************************************************* +* pwm_platform_release() +* +* Private Function by Sam Shen, 2009/8/12 +*/ +/*! +* \brief +* +* \retval 0 if success +*/ +static void pwm_platform_release +( + struct device *device /*!<; // please add parameters description her*/ +) +{ +} /* End of pwm_platform_release() */ + +/*!************************************************************************* + platform device struct define +****************************************************************************/ +#if 0 +static struct resource pwm_resources[] = { + [0] = { + .start = 0xf8011400, + .end = 0xf80117ff, + .flags = IORESOURCE_MEM, + }, +}; + +static u64 pwm_dma_mask = 0xffffffffUL; +#endif + +static struct platform_device pwm_device = { + .name = "wmt-pwm", + .id = 0, + .dev = { .release = pwm_platform_release, +#if 0 + .dma_mask = &pwm_dma_mask, + .coherent_dma_mask = ~0, +#endif + }, + .num_resources = 0, /* ARRAY_SIZE(btm_resources), */ + .resource = NULL, /* pwm_resources, */ +}; + +/*!************************************************************************* +* pwm_init() +* +* Private Function by Sam Shen, 2009/8/12 +*/ +/*! +* \brief +* +* \retval 0 if success +*/ +static int pwm_init(void) +{ + int ret; + dev_t dev_no; + + printk("Enter pwm_init\n"); + + if( pwm_dev_major ){ + dev_no = MKDEV(pwm_dev_major,pwm_dev_minor); + ret = register_chrdev_region(dev_no,pwm_dev_nr,"wmt-pwm"); + } + else { + ret = alloc_chrdev_region(&dev_no,pwm_dev_minor,pwm_dev_nr,"wmt-pwm"); + pwm_dev_major = MAJOR(dev_no); + } + + if( ret < 0 ){ + printk(KERN_ALERT "*E* can't get major %d\n",pwm_dev_major); + return ret; + } + + ret = platform_driver_register(&pwm_driver); + if (!ret) { + ret = platform_device_register(&pwm_device); + if (ret) + platform_driver_unregister(&pwm_driver); + } + + auto_pll_divisor(DEV_PWM,CLK_ENABLE,0,0); + if (g_pwm_param == 0) + pwm_get_env(); + + return ret; +} /* End of pwm_init() */ + +module_init(pwm_init); + +/*!************************************************************************* +* pwm_exit() +* +* Private Function by Sam Shen, 2009/8/12 +*/ +/*! +* \brief +* +* \retval 0 if success +*/ +static void pwm_exit(void) +{ + dev_t dev_no; + + printk(KERN_ALERT "Enter pwm_exit\n"); + + platform_driver_unregister(&pwm_driver); + platform_device_unregister(&pwm_device); + dev_no = MKDEV(pwm_dev_major,pwm_dev_minor); + unregister_chrdev_region(dev_no,pwm_dev_nr); + return; +} /* End of pwm_exit() */ + +module_exit(pwm_exit); + +MODULE_AUTHOR("WonderMedia Technologies, Inc."); +MODULE_DESCRIPTION("WMT [PWM] driver"); +MODULE_LICENSE("GPL"); + +/*--------------------End of Function Body -----------------------------------*/ + +#undef WMT_PWM_C + |