s3c6410 linux移植之五 led灯驱动
(2011-03-05 12:11)
分类: s3c6410笔记
/*******************************************************************************************
Copyright (C), 1996-2010, Shenzhen xx Co., ltd
FileName: clou_led.c
Author: pangyong
Version : 1.0
Date: 2010-12-23
Copyright (C), 1996-2010, Shenzhen xx Co., ltd
FileName: clou_led.c
Author: pangyong
Version : 1.0
Date: 2010-12-23
Description:
Version: 1.0 this is the moudle of the driver.
Function List:
1.
History:
<author> <time> <version > <desc>
pangyong 01/12/23 1.0 build this moudle
pangyong 11/04/12 1.0.1 changed the kernel is 2.6.36
*******************************************************************************************/
#include <linux/types.h>
#include <linux/cdev.h>
#include <linux/fs.h>
#include <linux/device.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/string.h>
#include <linux/platform_device.h>
#include <linux/errno.h>
#include <asm/uaccess.h>
#include <linux/delay.h>
#include <linux/miscdevice.h>
#include <asm/io.h>
#include <linux/poll.h>
#include <linux/wait.h>
#include <linux/interrupt.h>
#include <linux/sched.h>
#include <linux/ioctl.h>
#include <linux/spinlock.h>
#include <asm/system.h>
#include <linux/cdev.h>
#include <linux/mm.h>
#include <linux/irq.h>
#include <asm/irq.h>
#include <mach/hardware.h>
#include <linux/cdev.h>
#include <plat/gpio-cfg.h>
#include <plat/regs-timer.h>
#include <mach/map.h>
#include <linux/clk.h>
#include <linux/io.h>
#include <asm/system.h>
#include <asm/leds.h>
#include <asm/mach-types.h>
#include <asm/irq.h>
#include <mach/map.h>
#include <plat/regs-timer.h>
#include <mach/regs-irq.h>
#include <mach/regs-gpio.h>
#include <mach/gpio-bank-n.h>
#include <asm/mach/time.h>
#include <mach/tick.h>
#include <plat/clock.h>
#include <plat/cpu.h>
#include <linux/skbuff.h>
Version: 1.0 this is the moudle of the driver.
Function List:
1.
History:
<author> <time> <version > <desc>
pangyong 01/12/23 1.0 build this moudle
pangyong 11/04/12 1.0.1 changed the kernel is 2.6.36
*******************************************************************************************/
#include <linux/types.h>
#include <linux/cdev.h>
#include <linux/fs.h>
#include <linux/device.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/string.h>
#include <linux/platform_device.h>
#include <linux/errno.h>
#include <asm/uaccess.h>
#include <linux/delay.h>
#include <linux/miscdevice.h>
#include <asm/io.h>
#include <linux/poll.h>
#include <linux/wait.h>
#include <linux/interrupt.h>
#include <linux/sched.h>
#include <linux/ioctl.h>
#include <linux/spinlock.h>
#include <asm/system.h>
#include <linux/cdev.h>
#include <linux/mm.h>
#include <linux/irq.h>
#include <asm/irq.h>
#include <mach/hardware.h>
#include <linux/cdev.h>
#include <plat/gpio-cfg.h>
#include <plat/regs-timer.h>
#include <mach/map.h>
#include <linux/clk.h>
#include <linux/io.h>
#include <asm/system.h>
#include <asm/leds.h>
#include <asm/mach-types.h>
#include <asm/irq.h>
#include <mach/map.h>
#include <plat/regs-timer.h>
#include <mach/regs-irq.h>
#include <mach/regs-gpio.h>
#include <mach/gpio-bank-n.h>
#include <asm/mach/time.h>
#include <mach/tick.h>
#include <plat/clock.h>
#include <plat/cpu.h>
#include <linux/skbuff.h>
/* the key of debug */
//#define LED_DEBUG
#ifdef LED_DEBUG
#define DEBUG(fmt, arg...) printk(fmt, ##arg)
#else
#define DEBUG(fmt, arg...)
#endif
//#define LED_DEBUG
#ifdef LED_DEBUG
#define DEBUG(fmt, arg...) printk(fmt, ##arg)
#else
#define DEBUG(fmt, arg...)
#endif
#define LED_1 12
#define LED_2 13
#define LED_2 13
#define DEV_NAME "clou_led"
#define MISC_DEV_NAME "clou_led"
#define DRV_VERSION "1.0.1"
#define MISC_DEV_NAME "clou_led"
#define DRV_VERSION "1.0.1"
/* timer wakeup time : 1/2 second */
#define LED_TIMER_WUT jiffies+(HZ/2)
/* the Maximum num of devices, you can add multi-devices */
static unsigned int DEV_NUM_MAX;
static unsigned int DEV_NUM_MAX;
/* the private info of device */
struct clou_led_info
{
dev_t dev_id;
spinlock_t dev_lock;
struct mutex dev_mutex;
struct timer_list timer;
unsigned char time_flag;
};
struct clou_led_info
{
dev_t dev_id;
spinlock_t dev_lock;
struct mutex dev_mutex;
struct timer_list timer;
unsigned char time_flag;
};
struct resource clou_led_resource[] = {
};
};
/*******************************************************************************************
Function: static void ep3cxx_ps_release(struct device * dev)
Description: run this function when the device is release
Input: device
Return: no
Others: this function is keep the completeness of driver.
it is not some useful of function, but is must be in here.
*******************************************************************************************/
static void clou_led_release(struct device * dev)
{
printk(KERN_ALERT "%s:%s,%s\r\n", __FUNCTION__,__DATE__,__TIME__);
}
Function: static void ep3cxx_ps_release(struct device * dev)
Description: run this function when the device is release
Input: device
Return: no
Others: this function is keep the completeness of driver.
it is not some useful of function, but is must be in here.
*******************************************************************************************/
static void clou_led_release(struct device * dev)
{
printk(KERN_ALERT "%s:%s,%s\r\n", __FUNCTION__,__DATE__,__TIME__);
}
/* the devices, you can add some devices of this driver over there */
struct platform_device clou_led_device[]=
{
{
.name = DEV_NAME,
.id = 0,
.num_resources = ARRAY_SIZE(clou_led_resource),
.resource = clou_led_resource,
.dev =
{
.release = clou_led_release,
}
},
};
struct platform_device clou_led_device[]=
{
{
.name = DEV_NAME,
.id = 0,
.num_resources = ARRAY_SIZE(clou_led_resource),
.resource = clou_led_resource,
.dev =
{
.release = clou_led_release,
}
},
};
static void clou_led_timer(unsigned long data)
{
struct clou_led_info *timer_info = platform_get_drvdata(&clou_led_device[data]);
unsigned char reg = 0;
{
struct clou_led_info *timer_info = platform_get_drvdata(&clou_led_device[data]);
unsigned char reg = 0;
(timer_info->time_flag > 0) ? (reg = 0x01) : (reg = 0x00);
iowrite32((ioread32(S3C64XX_GPNDAT) & ~(0x01<<LED_1)) | (reg<<LED_1), S3C64XX_GPNDAT);
iowrite32((ioread32(S3C64XX_GPNDAT) & ~(0x01<<LED_2)) | (reg<<LED_2), S3C64XX_GPNDAT);
timer_info->time_flag = ~timer_info->time_flag;
timer_info->timer.expires = LED_TIMER_WUT;
add_timer(&timer_info->timer);
}
timer_info->timer.expires = LED_TIMER_WUT;
add_timer(&timer_info->timer);
}
/*******************************************************************************************
Function: static int clou_led_open(struct inode *inode,struct file *filp)
Description: run this function when the device is open.
Input: struct inode *inode(the file inode)
struct file *filp(the file )
Return: 0 is success
others is error
Others:
*******************************************************************************************/
static int clou_led_open(struct inode *inode,struct file *filp)
{
struct clou_led_info *open_info = NULL;
unsigned int idx;
unsigned num = 0;
Function: static int clou_led_open(struct inode *inode,struct file *filp)
Description: run this function when the device is open.
Input: struct inode *inode(the file inode)
struct file *filp(the file )
Return: 0 is success
others is error
Others:
*******************************************************************************************/
static int clou_led_open(struct inode *inode,struct file *filp)
{
struct clou_led_info *open_info = NULL;
unsigned int idx;
unsigned num = 0;
idx = DEV_NUM_MAX;
DEBUG(KERN_ALERT "%s:%s,%s\r\n", __FUNCTION__,__DATE__,__TIME__);
/* get the platform_device, if have multi devices,judge the device of file inode*/
for(num = 0; num < DEV_NUM_MAX; num++)
{
/* get the private data form the platform_device */
open_info = platform_get_drvdata(&clou_led_device[num]);
/* use the file inode judge the device */
if(open_info->dev_id == iminor(inode))
break;
}
for(num = 0; num < DEV_NUM_MAX; num++)
{
/* get the private data form the platform_device */
open_info = platform_get_drvdata(&clou_led_device[num]);
/* use the file inode judge the device */
if(open_info->dev_id == iminor(inode))
break;
}
/* make the filp private_data pointer the platform device private */
filp->private_data = open_info;
filp->private_data = open_info;
/* get the mutex */
mutex_lock(&open_info->dev_mutex);
mutex_lock(&open_info->dev_mutex);
/* set the timer */
init_timer(&open_info->timer);
open_info->timer.function = &clou_led_timer;
open_info->timer.data = (unsigned long)num;
open_info->timer.expires = LED_TIMER_WUT;
add_timer(&open_info->timer);
init_timer(&open_info->timer);
open_info->timer.function = &clou_led_timer;
open_info->timer.data = (unsigned long)num;
open_info->timer.expires = LED_TIMER_WUT;
add_timer(&open_info->timer);
open_info->time_flag = 0x00;
/* release the mutex */
mutex_unlock(&open_info->dev_mutex);
/* define the driver is not llseek function */
nonseekable_open(inode, filp);
return 0;
}
mutex_unlock(&open_info->dev_mutex);
/* define the driver is not llseek function */
nonseekable_open(inode, filp);
return 0;
}
/*******************************************************************************************
Function: static ssize_t clou_led_read(struct file *filp,char __user *buffer,size_t size,loff_t *offset)
Description: run this function when the device is read.
Input: struct file *filp
char __user *buffer
size_t size
loff_t *offset
Return: the size of read succeed.
Others: it is not some usefull function now.
*******************************************************************************************/
static ssize_t clou_led_read(struct file *filp,char __user *buffer,size_t size,loff_t *offset)
{
DEBUG(KERN_ALERT "%s:%s,%s\r\n", __FUNCTION__,__DATE__,__TIME__);
return size;
}
Function: static ssize_t clou_led_read(struct file *filp,char __user *buffer,size_t size,loff_t *offset)
Description: run this function when the device is read.
Input: struct file *filp
char __user *buffer
size_t size
loff_t *offset
Return: the size of read succeed.
Others: it is not some usefull function now.
*******************************************************************************************/
static ssize_t clou_led_read(struct file *filp,char __user *buffer,size_t size,loff_t *offset)
{
DEBUG(KERN_ALERT "%s:%s,%s\r\n", __FUNCTION__,__DATE__,__TIME__);
return size;
}
/*******************************************************************************************
Function: static ssize_t clou_led_write(struct file *filp,const char __user *buffer,size_t size,loff_t *offset)
Description: run this function when the device is write.
Input: struct file *filp
const char __user *buffer
size_t size
loff_t *offset
Return: the size of write succeed.
Others: this function is finished operates of below:
*******************************************************************************************/
static ssize_t clou_led_write(struct file *filp,const char __user *buffer,size_t size,loff_t *offset)
{
DEBUG(KERN_ALERT "%s:%s,%s\r\n", __FUNCTION__,__DATE__,__TIME__);
Function: static ssize_t clou_led_write(struct file *filp,const char __user *buffer,size_t size,loff_t *offset)
Description: run this function when the device is write.
Input: struct file *filp
const char __user *buffer
size_t size
loff_t *offset
Return: the size of write succeed.
Others: this function is finished operates of below:
*******************************************************************************************/
static ssize_t clou_led_write(struct file *filp,const char __user *buffer,size_t size,loff_t *offset)
{
DEBUG(KERN_ALERT "%s:%s,%s\r\n", __FUNCTION__,__DATE__,__TIME__);
return 0;
}
}
/*******************************************************************************************
Function: static int clou_led_ioctl(struct inode *inode,struct file *filp,unsigned int cmd,unsigned long arg)
Description: run this function when the device is close.
Input: struct inode *inode
struct file *filp
unsigned int cmd
unsigned long arg
Return: 0 is success
others is error
Others:
*******************************************************************************************/
static long clou_led_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
/* get the private_data form the file */
//struct clou_led_info *ioctl_info = filp->private_data;
unsigned char ioctl_reg = 0x00;
Function: static int clou_led_ioctl(struct inode *inode,struct file *filp,unsigned int cmd,unsigned long arg)
Description: run this function when the device is close.
Input: struct inode *inode
struct file *filp
unsigned int cmd
unsigned long arg
Return: 0 is success
others is error
Others:
*******************************************************************************************/
static long clou_led_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
/* get the private_data form the file */
//struct clou_led_info *ioctl_info = filp->private_data;
unsigned char ioctl_reg = 0x00;
DEBUG(KERN_ALERT "%s:%s,%s\r\n", __FUNCTION__,__DATE__,__TIME__);
(arg > 0) ? (ioctl_reg = 0x01) : (ioctl_reg = 0x00);
switch(cmd)
{
case 0:
iowrite32((ioread32(S3C64XX_GPNDAT) & ~(0x01<<LED_1)) | (ioctl_reg<<LED_1), S3C64XX_GPNDAT);
break;
case 1:
iowrite32((ioread32(S3C64XX_GPNDAT) & ~(0x01<<LED_2)) | (ioctl_reg<<LED_2), S3C64XX_GPNDAT);
break;
default:
break;
}
switch(cmd)
{
case 0:
iowrite32((ioread32(S3C64XX_GPNDAT) & ~(0x01<<LED_1)) | (ioctl_reg<<LED_1), S3C64XX_GPNDAT);
break;
case 1:
iowrite32((ioread32(S3C64XX_GPNDAT) & ~(0x01<<LED_2)) | (ioctl_reg<<LED_2), S3C64XX_GPNDAT);
break;
default:
break;
}
return 0;
}
/*******************************************************************************************
Function: static int clou_led_close(struct inode *inode,struct file *filp)
Description: run this function when the device is close.
Input: struct inode *inode
struct file *filp
Return: 0 is success
others is error
Others: this function is finished operates of below:
*******************************************************************************************/
static int clou_led_close(struct inode *inode,struct file *filp)
{
DEBUG(KERN_ALERT "%s:%s,%s\r\n", __FUNCTION__,__DATE__,__TIME__);
Function: static int clou_led_close(struct inode *inode,struct file *filp)
Description: run this function when the device is close.
Input: struct inode *inode
struct file *filp
Return: 0 is success
others is error
Others: this function is finished operates of below:
*******************************************************************************************/
static int clou_led_close(struct inode *inode,struct file *filp)
{
DEBUG(KERN_ALERT "%s:%s,%s\r\n", __FUNCTION__,__DATE__,__TIME__);
return 0;
}
}
/* the file_operation */
struct file_operations clou_led_opt = {
.owner = THIS_MODULE,
.unlocked_ioctl = clou_led_ioctl,
.open = clou_led_open,
.read = clou_led_read,
.write = clou_led_write,
.release = clou_led_close,
};
struct file_operations clou_led_opt = {
.owner = THIS_MODULE,
.unlocked_ioctl = clou_led_ioctl,
.open = clou_led_open,
.read = clou_led_read,
.write = clou_led_write,
.release = clou_led_close,
};
/* the misc_device */
static struct miscdevice clou_led_miscdev[] ={
{
.minor = MISC_DYNAMIC_MINOR,
.name = MISC_DEV_NAME,
.fops = &clou_led_opt,
},
};
static struct miscdevice clou_led_miscdev[] ={
{
.minor = MISC_DYNAMIC_MINOR,
.name = MISC_DEV_NAME,
.fops = &clou_led_opt,
},
};
/*******************************************************************************************
Function: static int __devinit clou_led_probe(struct platform_device *dev)
Description: run this function when the device is platform_device_register.
Input: struct platform_device *dev
Return: 0 is success
others is error
Others: this function is finished operates of below:
*******************************************************************************************/
static int __devinit clou_led_probe(struct platform_device *dev)
{
struct clou_led_info *priv_info = NULL;
int ret = 0;
Function: static int __devinit clou_led_probe(struct platform_device *dev)
Description: run this function when the device is platform_device_register.
Input: struct platform_device *dev
Return: 0 is success
others is error
Others: this function is finished operates of below:
*******************************************************************************************/
static int __devinit clou_led_probe(struct platform_device *dev)
{
struct clou_led_info *priv_info = NULL;
int ret = 0;
DEBUG(KERN_INFO "%s:%s,%s\r\n", __FUNCTION__,__DATE__,__TIME__);
/* reauest the menory and clear this menory */
priv_info = kzalloc(sizeof(struct clou_led_info), GFP_KERNEL);
if (!priv_info) {
ret = -ENOMEM;
goto err_out;
}
/* registe the misdevice */
ret=misc_register(&clou_led_miscdev[dev->id]);
if(ret)
{
printk("cannot register clou_led_misc miscdev!\n");
goto err;
}
priv_info = kzalloc(sizeof(struct clou_led_info), GFP_KERNEL);
if (!priv_info) {
ret = -ENOMEM;
goto err_out;
}
/* registe the misdevice */
ret=misc_register(&clou_led_miscdev[dev->id]);
if(ret)
{
printk("cannot register clou_led_misc miscdev!\n");
goto err;
}
/* config GPN12 is output and pull_up */
iowrite32((ioread32(S3C64XX_GPNDAT) & ~(0x3<<4)) | (0x1<<4), S3C64XX_GPNDAT);
iowrite32((ioread32(S3C64XX_GPNDAT) & ~(0x3<<4)) | (0x2<<4), S3C64XX_GPNDAT);
/* config GPN13 (DATA) is output and pull_up */
iowrite32((ioread32(S3C64XX_GPNDAT) & ~(0x3<<6)) | (0x1<<6), S3C64XX_GPNDAT);
iowrite32((ioread32(S3C64XX_GPNDAT) & ~(0x3<<6)) | (0x2<<6), S3C64XX_GPNDAT);
iowrite32((ioread32(S3C64XX_GPNDAT) & ~(0x3<<4)) | (0x1<<4), S3C64XX_GPNDAT);
iowrite32((ioread32(S3C64XX_GPNDAT) & ~(0x3<<4)) | (0x2<<4), S3C64XX_GPNDAT);
/* config GPN13 (DATA) is output and pull_up */
iowrite32((ioread32(S3C64XX_GPNDAT) & ~(0x3<<6)) | (0x1<<6), S3C64XX_GPNDAT);
iowrite32((ioread32(S3C64XX_GPNDAT) & ~(0x3<<6)) | (0x2<<6), S3C64XX_GPNDAT);
/* set the id of device is the minor of misdevice */
priv_info->dev_id = clou_led_miscdev[dev->id].minor;
DEBUG(KERN_ALERT "dev_id.minor = %d\n", priv_info->dev_id);
priv_info->dev_id = clou_led_miscdev[dev->id].minor;
DEBUG(KERN_ALERT "dev_id.minor = %d\n", priv_info->dev_id);
/* initialize the spin_lock */
spin_lock_init(&priv_info->dev_lock);
spin_lock_init(&priv_info->dev_lock);
/* initialize the mutex */
mutex_init(&priv_info->dev_mutex);
/* set the platform_drvdata */
platform_set_drvdata(dev, priv_info);
mutex_init(&priv_info->dev_mutex);
/* set the platform_drvdata */
platform_set_drvdata(dev, priv_info);
return 0;
/* the handle of error */
err:
misc_deregister(&clou_led_miscdev[dev->id]);
kfree(priv_info);
err_out:
return ret;
}
err:
misc_deregister(&clou_led_miscdev[dev->id]);
kfree(priv_info);
err_out:
return ret;
}
/*******************************************************************************************
Function: static int __devexit clou_led_remove(struct platform_device *dev)
Description: run this function when the device is remove form the kernel module.
Input: struct platform_device *dev
Return: 0 is success
others is error
Others: this function is finished operates of below:
*******************************************************************************************/
static int __devexit clou_led_remove(struct platform_device *dev)
{
/* get the platform_device private_data*/
struct clou_led_info *remove_priv = platform_get_drvdata(dev);
Function: static int __devexit clou_led_remove(struct platform_device *dev)
Description: run this function when the device is remove form the kernel module.
Input: struct platform_device *dev
Return: 0 is success
others is error
Others: this function is finished operates of below:
*******************************************************************************************/
static int __devexit clou_led_remove(struct platform_device *dev)
{
/* get the platform_device private_data*/
struct clou_led_info *remove_priv = platform_get_drvdata(dev);
DEBUG(KERN_ALERT "%s:%s,%s\r\n", __FUNCTION__,__DATE__,__TIME__);
/* delete the timer */
del_timer(&remove_priv->timer);
/* platform_device private_data pointer is NULL */
platform_set_drvdata(dev, NULL);
del_timer(&remove_priv->timer);
/* platform_device private_data pointer is NULL */
platform_set_drvdata(dev, NULL);
/* deregister the mis device */
misc_deregister(&clou_led_miscdev[dev->id]);
misc_deregister(&clou_led_miscdev[dev->id]);
/* release the request menory */
kfree(remove_priv);
return 0;
}
kfree(remove_priv);
return 0;
}
/* platform_driver */
static struct platform_driver clou_led_driver = {
.probe = clou_led_probe,
.remove = __devexit_p(clou_led_remove),
.driver = {
.owner = THIS_MODULE,
.name = DEV_NAME,
},
};
static struct platform_driver clou_led_driver = {
.probe = clou_led_probe,
.remove = __devexit_p(clou_led_remove),
.driver = {
.owner = THIS_MODULE,
.name = DEV_NAME,
},
};
/*******************************************************************************************
Function: static int __init clou_led_init(void)
Description: run this function when the device is insert the kernel module.
Input: void
Return: 0 is success
others is error
Others: this function is finished operates of below:
*******************************************************************************************/
static int __init clou_led_init(void)
{
int ret = 0;
unsigned int num = 0;
DEBUG(KERN_ALERT "%s:%s,%s\r\n", __FUNCTION__,__DATE__,__TIME__);
printk(KERN_INFO "%s CLOU_LED Driver, V%s\n", DEV_NAME, DRV_VERSION);
/* get the max device num */
DEV_NUM_MAX = sizeof(clou_led_device) / sizeof(struct platform_device);
Function: static int __init clou_led_init(void)
Description: run this function when the device is insert the kernel module.
Input: void
Return: 0 is success
others is error
Others: this function is finished operates of below:
*******************************************************************************************/
static int __init clou_led_init(void)
{
int ret = 0;
unsigned int num = 0;
DEBUG(KERN_ALERT "%s:%s,%s\r\n", __FUNCTION__,__DATE__,__TIME__);
printk(KERN_INFO "%s CLOU_LED Driver, V%s\n", DEV_NAME, DRV_VERSION);
/* get the max device num */
DEV_NUM_MAX = sizeof(clou_led_device) / sizeof(struct platform_device);
DEBUG(KERN_ALERT "%d,%d,%d\n", sizeof(clou_led_device), sizeof(struct platform_device), DEV_NUM_MAX );
/* register the platform devices */
for(num = 0; num < DEV_NUM_MAX; num++)
{
ret = platform_device_register ( &clou_led_device[num] );
if ( ret )
{
platform_device_unregister ( &clou_led_device[num] );
printk ( "platform_device_register is fail!\n" );
return ret;
}
}
/* register the platform devices */
for(num = 0; num < DEV_NUM_MAX; num++)
{
ret = platform_device_register ( &clou_led_device[num] );
if ( ret )
{
platform_device_unregister ( &clou_led_device[num] );
printk ( "platform_device_register is fail!\n" );
return ret;
}
}
/* register the platform driver */
ret = platform_driver_register ( &clou_led_driver );
if ( ret )
{
printk ( "platform_driver_register is fail!\n" );
platform_driver_unregister ( &clou_led_driver );
return ret;
}
ret = platform_driver_register ( &clou_led_driver );
if ( ret )
{
printk ( "platform_driver_register is fail!\n" );
platform_driver_unregister ( &clou_led_driver );
return ret;
}
DEBUG ( "platform_driver_register is ok!\n" );
return ret;
return ret;
}
/*******************************************************************************************
Function: static void __exit clou_led_exit ( void )
Description: run this function when the device is exit the kernel module.
Input: void
Return: void
Others: this function is finished operates of below:
1,unregister the platform driver
2,unregister the platform devices
*******************************************************************************************/
static void __exit clou_led_exit(void)
{
unsigned int num = 0;
Function: static void __exit clou_led_exit ( void )
Description: run this function when the device is exit the kernel module.
Input: void
Return: void
Others: this function is finished operates of below:
1,unregister the platform driver
2,unregister the platform devices
*******************************************************************************************/
static void __exit clou_led_exit(void)
{
unsigned int num = 0;
DEBUG(KERN_ALERT "%s:%s,%s\r\n", __FUNCTION__,__DATE__,__TIME__);
/* unregister the platform driver */
platform_driver_unregister ( &clou_led_driver );
platform_driver_unregister ( &clou_led_driver );
/* unregister the platform devices */
for(num = 0; num < DEV_NUM_MAX; num++)
{
platform_device_unregister ( &clou_led_device[num] );
}
}
for(num = 0; num < DEV_NUM_MAX; num++)
{
platform_device_unregister ( &clou_led_device[num] );
}
}
module_init ( clou_led_init );
module_exit ( clou_led_exit );
module_exit ( clou_led_exit );
MODULE_AUTHOR("pangyong");
MODULE_DESCRIPTION("this is clou_led driver module");
MODULE_LICENSE("Dual BSD/GPL");
MODULE_DESCRIPTION("this is clou_led driver module");
MODULE_LICENSE("Dual BSD/GPL");


