Chinaunix首页 | 论坛 | 博客
  • 博客访问: 505430
  • 博文数量: 157
  • 博客积分: 3010
  • 博客等级: 中校
  • 技术积分: 1608
  • 用 户 组: 普通用户
  • 注册时间: 2008-08-16 09:30
文章存档

2010年(155)

2008年(2)

我的朋友

分类: LINUX

2010-03-12 20:07:37

struct IIC_dev{
        wait_queue_head_t rq
; // 读取等待队列
        
uint8_t *buffer;
        
uint32_t size;
        
uint32_t index;
        
struct semaphore sem;
        
struct cdev cdev;
};
struct IIC_dev *my_dev;

static int __init IIC_init(void)
{
        
// 1. 分配主设备号
        dev_t devno
= MKDEV( major, minor );
        
int ret = register_chrdev_region( devno, 1, DEVICE );//(设备号,注册号,名称)
        
if( ret < 0 )
        
{
          printk
(KERN_DEBUG "register major number failed with %d\n", ret);
          
return ret;
        
}
        printk
(KERN_DEBUG "%s:register major number OK\n",DEVICE);

        
// 2. 注册设备
        my_dev
= kmalloc(sizeof(struct IIC_dev), GFP_KERNEL);
        
memset( my_dev, 0, sizeof(struct IIC_dev) );
        cdev_init
( &my_dev->cdev, &fops );
        my_dev
->cdev.ops = &fops;
        my_dev
->cdev.owner = THIS_MODULE;
        ret
= cdev_add( &my_dev->cdev, devno, 1 );
        
if( ret < 0 )
        
{
          printk
(KERN_DEBUG "register device failed with %d\n", ret);
          
return ret;
        
}
        printk
(KERN_DEBUG "%s:register device OK\n",DEVICE);

        
// 3. 分配本驱动要使用的内存
        my_dev
->index = 0;
        my_dev
->size = 128;
        my_dev
->buffer = kmalloc( my_dev->size, GFP_KERNEL );
        
if( NULL == my_dev->buffer )
        
{
          printk
(KERN_DEBUG "kmalloc failed\n");
          
return -ENOMEM;
        
}
        printk
(KERN_DEBUG "%s:kmalloc buffer OK\n",DEVICE);

        
// 4. 初始化信号量
        init_MUTEX
( &(my_dev->sem) );
        printk
(KERN_DEBUG "%s:init semaphore OK\n",DEVICE);

        
// 5. 初始化等待队列头
        init_waitqueue_head
(&my_dev->rq);

        
// 6. Remap IIC 寄存器
        address_map
();

        
// 7. 设置 s3c2410 IIC
        
unsigned int tmp = ioread32( R_GPEUP );
        tmp
|= 0xc000; //Pull-up disable
        iowrite32
( tmp, R_GPEUP );
        tmp
= ioread32( R_GPECON );
        tmp
|= 0xa0000000; //GPE15:IICSDA , GPE14:IICSCL
        iowrite32
( tmp, R_GPECON );
        
return 0;
}


static void __exit IIC_exit(void)
{
        dev_t devno
= MKDEV( major, minor );
        
// 以相反的顺序清除
        address_unmap
();
        kfree
( my_dev->buffer );
        cdev_del
( &my_dev->cdev );
        kfree
( my_dev );
        printk
(KERN_DEBUG "%s:kfree OK\n",DEVICE);
        unregister_chrdev_region
( devno, 1 );
        printk
(KERN_DEBUG "%s:unregister device OK\n",DEVICE);
}

static void set_slave_recv_mode(void)
{
        iowrite8
( 0xE2, R_IICCON ); // 使能ACK,使能中断
        iowrite8
( 0xAA, R_IICADD ); // 从器件地址
        iowrite8
( 0x10, R_IICSTAT); // 设置从器件接收模式
        barrier
(); // 强制写入寄存器
}

int IIC_open(struct inode *inode, struct file *file)
{
        
struct IIC_dev *dev = container_of(inode->i_cdev, struct IIC_dev, cdev);
        
file->private_data = dev;
        
if( down_interruptible(&dev->sem) )
                
return -ERESTARTSYS;
        set_slave_recv_mode
();
        
int ret = request_irq( IRQ_IIC, interrupt_handleSA_INTERRUPT, DEVICE, (void*)dev );
        
if( ret )
        
{
                printk
( KERN_INFO "I2C: can't get assigned irq %d\n", IRQ_IIC );
        
}
        
return 0;
}

阅读(1087) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~