S3C2440扩展引脚普通IO的驱动源码

来源:互联网 发布:二级msoffice题库软件 编辑:程序博客网 时间:2024/05/29 05:00

 #include <linux/config.h>
#include <linux/fs.h>
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <asm/io.h>
#include <asm/uaccess.h>

#define NAME "led_drv"
static int major = 231;
//MODULE_AUTHOR("gec");
//MODULE_DESCRIPTION("LED Driver");
//MODULE_LICENSE("GPL");
//module_param(major, int, 0);
//MODULE_PARM_DESC(major, "Major device number");

#define S3C2410_ADDR(x)   (0xF0000000 + (x))
#define S3C24XX_VA_GPIO    S3C2410_ADDR(0x00E00000)
#define S3C2410_GPIOREG(x) ((x) + S3C24XX_VA_GPIO)

#define S3C2410_GPACON    *((volatile unsigned long*)S3C2410_GPIOREG(0x00))
#define S3C2410_GPADAT    *((volatile unsigned long*)S3C2410_GPIOREG(0x04))

// 用到B6,B0?
// Port B
#define S3C2410_GPBCON    *((volatile unsigned long*)S3C2410_GPIOREG(0x10))
#define S3C2410_GPBDAT    *((volatile unsigned long*)S3C2410_GPIOREG(0x14))
#define S3C2410_GPBUP    *((volatile unsigned long*)S3C2410_GPIOREG(0x18))
//用到G7,G6?
// Port G
#define S3C2410_GPGCON    *((volatile unsigned long*)S3C2410_GPIOREG(0x60))
#define S3C2410_GPGDAT    *((volatile unsigned long*)S3C2410_GPIOREG(0x64))
#define S3C2410_GPGUP    *((volatile unsigned long*)S3C2410_GPIOREG(0x68))

#define Led1_ON()       (S3C2410_GPBDAT &= ~(1<<6))
#define Led1_OFF()      (S3C2410_GPBDAT |= (1<<6))
#define Led2_ON()       (S3C2410_GPBDAT &= ~(1<<0))
#define Led2_OFF()      (S3C2410_GPBDAT |= (1<<0))
#define Led3_ON()       (S3C2410_GPGDAT &= ~(1<<7))
#define Led3_OFF()      (S3C2410_GPGDAT |= (1<<7))
#define Led4_ON()       (S3C2410_GPGDAT &= ~(1<<6))
#define Led4_OFF()      (S3C2410_GPGDAT |= (1<<6))

 


/*
 * LedDisp函数根据参数led来显示相应的Led。
 */
void LedDisp(int led)
{
    int mask;
    // 某位位置为1点亮,否则熄灭,可无限添加更多效果
    // 0 全灭, 1-4依次单独点亮灯1-4,熄灭其余
    int arr_mask[] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,};// 效果掩码
    if( led < 0 || led >= (sizeof(arr_mask)/sizeof(arr_mask[0])) )
        return;
    mask = arr_mask[led];// 根据输入的数字选择效果

    (mask & (1<<0)) ?  Led1_ON() :  Led1_OFF(); // 对应位置为1点亮,否则熄灭
    (mask & (1<<1)) ?  Led2_ON() :  Led2_OFF();
    (mask & (1<<2)) ?  Led3_ON() :  Led3_OFF();
    (mask & (1<<3)) ?  Led4_ON() :  Led4_OFF();
}

static int led_drv_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{
 printk("led- ioctl: param %u %lu/n", cmd, arg);
    LedDisp(arg);
 return 0;
}

static int led_drv_open(struct inode *inode, struct file *file)
{
  unsigned m = iminor(inode);
  if (m > 63)
   return -EINVAL;
  printk("LED driver opened!/n");
  return nonseekable_open(inode, file);
}

static int led_drv_release(struct inode *inode, struct file *file)
{
  printk("LED driver released!/n");
  return 0;
}

static struct file_operations led_drv_fops = {
  .owner   = THIS_MODULE,
  .ioctl   = led_drv_ioctl,
  .open    = led_drv_open,
  .release = led_drv_release,
};

static int __init led_drv_init(void)
{
    int temp;
 int ret;
 unsigned long tmp;
  printk("LED Driver./n");
 /* 注册LED设备 */
 ret = register_chrdev(major, NAME, &led_drv_fops);
  if (ret < 0) {
    printk("Unable to register character device!/n");
    return ret;
  }
 /*
  *初始化GPA-IO寄存器
  */
  // B6,B0,G7,G6 for output
 temp = S3C2410_GPBCON & (~((3<<12) | (3<<0))); // 屏蔽
 S3C2410_GPBCON = temp | (1<<12) | (1<<0);

 temp = S3C2410_GPGCON & (~((3<<14) | (3<<12))); // 屏蔽
 S3C2410_GPGCON = temp | (1<<14) | (1<<12);

    // 是否上拉
    S3C2410_GPBUP &= ~((1<<6) | (1<<0));  // enable poll up
    S3C2410_GPGUP &= ~((1<<7) | (1<<6));  // enable poll up

    //S3C2410_GPBUP |= (1<<6) | (1<<0);  // disable poll up
    //S3C2410_GPGUP |= (1<<7) | (1<<6);  // disable poll up


    // 初始化B6,B0,G7,G6输出高电平,可能点亮或者熄灭LED
    S3C2410_GPBDAT |= (1<<6) | (1<<0);
    S3C2410_GPGDAT |= (1<<7) | (1<<6);


 printk("LED Test Driver initiated./n");
 return 0;
}
static void __exit led_drv_cleanup(void)
{
  int ret;
  ret = unregister_chrdev(major, NAME);
  if (ret < 0)
    printk("Unable to register character device!/n");
  else
    printk("LED Test Driver unloaded!");
}
module_init(led_drv_init);
module_exit(led_drv_cleanup);

 

原创粉丝点击