发博文
microcreat

microcreat.blog.chinaunix.net

http://blog.sina.com.cn/u/2159951952   
个人资料
  • 博客访问:31000
  • 博文数量:28
  • 博客积分:1632
  • 博客等级:上尉
  • 注册时间:2010-04-02 21:19:49
订阅我的博客
  • 订阅
  • 订阅到鲜果
  • 订阅到抓虾
  • 订阅到Google
字体大小: 博文
分类: s3c6410笔记


/*******************************************************************************************
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>
/* 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_1                     12
#define LED_2                     13
#define DEV_NAME        "clou_led"
#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;
/* 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 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__);
}
/* 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,
  }
    },
};
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;

    (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);
}
/*******************************************************************************************
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;
  }
 /* make the filp private_data pointer the platform device private */
 filp->private_data = open_info;
 /* get the 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);
 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;
}
/*******************************************************************************************
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__);
 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;
 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;
  }

    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__);
 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,
};
/* the misc_device */
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;
 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;
        }
 /* 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);
 /* 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);
 /* initialize the spin_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);
 return 0;
 /* the handle of error */
 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);
 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);
 /* deregister the mis device */
 misc_deregister(&clou_led_miscdev[dev->id]);
 /* release the request menory */
 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,
    },
};
/*******************************************************************************************
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 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;
    }
    DEBUG ( "platform_driver_register is ok!\n" );
 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;
 DEBUG(KERN_ALERT "%s:%s,%s\r\n", __FUNCTION__,__DATE__,__TIME__);
 /* unregister the platform 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] );
  } 
}
module_init ( clou_led_init );
module_exit ( clou_led_exit );
MODULE_AUTHOR("pangyong");
MODULE_DESCRIPTION("this is clou_led driver module");
MODULE_LICENSE("Dual BSD/GPL");

[发评论] 评论 重要提示:警惕虚假中奖信息!
  • chinaunix网友 2011-03-27 18:08
    很好的, 收藏了 推荐一个博客,提供很多免费软件编程电子书下载: http://free-ebooks.appspot.com
  • chinaunix网友 2011-03-07 21:53
    HAO !
亲,您还没有登录,请[登录][注册]后再进行评论