📄 at24c01a.c
字号:
/*======================================================
*
* File Name:
* ---------
* at24c01a.c
*
*
* Author:
* -------
* zhang dahai
*
* Email:
* ------
* olivercheung@126.com
*
* QQ & MSN;
* ---------
* 334654529, olivercheung2005@yahoo.com.cn
*
* Modification History:
* -----------------
* 2006-8-23(21:09), zhang dahai, created.
*
*
======================================================*/
#ifndef __KERNEL__
#define __KERNEL__
#endif
/* includes */
#include <linux/kernel.h> /* printk() */
#include <linux/module.h> /*this is a kernel module, so ....*/
#include <linux/interrupt.h>
#include <linux/init.h> /*module_init, module_exit, etc*/
#include <linux/types.h> /* size_t */
#include <linux/sched.h> /* current and everything */
#include <linux/fs.h> /*register_chrdev, file etc*/
#include <asm/uaccess.h> /*copy_to_user, copy_from_user*/
#include <asm/hardware.h>
#include <asm/irq.h> /*request_irq, etc*/
#include <asm/io.h>
#include "at24c01a.h"
/*===========================================*/
/* defines */
/*===========================================*/
static unsigned char slvAddr;
static unsigned char ack = 0 ;
/*===========================================*/
/* globals */
/*===========================================*/
#define IRQ_IIC INT_IIC
static char * dev_idkp = IIC_NAME; /*for request_irq()*/
/*===========================================*/
/* functiona */
/*===========================================*/
void delay( void )
{
unsigned char i ;
for( i = 0 ; i < 100 ; i ++ )
{
;
}
}
static ssize_t at24c01a_read(struct file *filp, char *buf, size_t count, loff_t *l)
{
char readData ;
unsigned char readAddress ;
readAddress = count ;
//---------send control byte-----------
#ifdef DEBUG
printk("enter at2410a_read( )\n");
printk("send control byte.\n");
#endif
slvAddr = 0xa0;
IICDS = slvAddr; // 0xa0
IICSTAT=0xf0; // Master Tx,Start
#ifdef DEBUG
printk("wait ACK\n");
#endif
while( ack == 0 ) ;
ack = 0 ;
//------------send address------------
#ifdef DEBUG
printk("send address\n");
#endif
IICDS = readAddress;
IICCON = 0xaf; // resumes IIC operation.
#ifdef DEBUG
printk("wait ACK\n");
#endif
while( ack == 0 ) ;
ack = 0 ;
//-----------send control byte---------
#ifdef DEBUG
printk("send control byte\n");
#endif
IICDS = slvAddr|0x01; // 0xa1:R
IICSTAT=0xb0; // Master Rx,Start
IICCON=0xaf; // resumes IIC operation.
#ifdef DEBUG
printk("wait ACK\n");
#endif
while( ack == 0 ) ;
ack = 0 ;
#ifdef DEBUG
printk("READ \n");
#endif
readData = IICDS;
#ifdef DEBUG
printk("readData = 0x%x\n",readData );
#endif
//-------------Loop Start------------
#ifdef DEBUG
printk("-Loop Start\n" );
#endif
IICCON = 0xaf & (~0x80) ;
#ifdef DEBUG
printk("wait ACK\n");
#endif
while( ack == 0 ) ;
ack = 0 ;
//-------------get data ------------
#ifdef DEBUG
printk("READ \n");
#endif
readData = IICDS;
#ifdef DEBUG
printk("readData = 0x%x\n",readData );
#endif
//-------Loop End--------
#ifdef DEBUG
printk("-Loop end\n" );
#endif
IICSTAT = 0x90;
IICCON = 0xaf;
#ifdef DEBUG
printk("coping Data from kernel to user......");
#endif
copy_to_user( buf , &readData , 1 );
#ifdef DEBUG
printk("done\n");
#endif
return 1 ;
}
static ssize_t at24c01a_write(struct file *filp, const char *buf, size_t count, loff_t *l)
{
unsigned char i = 0 ;
unsigned char writeData[2] ;
#ifdef DEBUG
printk("enter at24c01a_write()\n");
printk("coping Data from user to kernel, thery are:\n");
#endif
copy_from_user( writeData , buf , count ) ;
#ifdef DEBUG
for( i = 0 ; i < count ; i ++ )
{
printk("0x%x ", writeData[ i ]);
}
#endif
// ---------send control byte---------
#ifdef DEBUG
printk("send control byte\n");
#endif
slvAddr = 0xa0;
IICDS = slvAddr; // 0xa0
IICSTAT=0xf0; // Master Tx,Start
//-----------wait ACK---------------
#ifdef DEBUG
printk("wait ACK\n");
#endif
while( ack == 0 ) ;
ack = 0 ;
//-----------send address--------------
#ifdef DEBUG
printk("send address\n");
#endif
IICDS = writeData[ 0 ];
IICCON = 0xaf; // resumes IIC operation.
//------------wait ACK---------------
#ifdef DEBUG
printk("wait ACK\n");
#endif
while( ack == 0 ) ;
ack = 0 ;
//-------------send data -------------
#ifdef DEBUG
printk("send data\n");
#endif
IICDS = writeData[ 1 ] ; //0x69; //Test
IICCON = 0xaf; // resumes IIC operation.
//-------------wait ACK ----------
#ifdef DEBUG
printk("wait ACK\n");
#endif
while( ack == 0 ) ;
ack = 0 ;
//-------------end send---------------
#ifdef DEBUG
printk("end send\n");
#endif
IICSTAT = 0xd0; // stop Master Tx condition
IICCON = 0xaf; // resumes IIC operation.
//--------wait until stop condtion is in effect.------
#ifdef DEBUG
printk("wait until stop condtion is in effect.\n");
#endif
delay();
#ifdef DEBUG
printk("exit at24c01a_write()\n\n");
#endif
}
static int at24c01a_open(struct inode *inode, struct file *filp)
{
int ret;
if ((ret = request_irq( IRQ_IIC, at24c01a_handler, SA_INTERRUPT,
IIC_NAME, dev_idkp)))
{
printk("at24c01a interrrupt: failed to register IRQ\n");
free_irq(IRQ_IIC, dev_idkp);
return ret;
}
#ifdef DEBUG
printk("Successful to open AT24C01A!\n");
#endif
disable_irq( IRQ_IIC ); /*disable at24c01a interrupt on ARM */
IICADD = 0x10; /* S3C44B0X slave address*/
IICCON = ( 1 << 7 )|( 0 << 6 )|( 1 << 5 )|( 0xf ); /*Enable interrupt, IICCLK=MCLK/16, Enable ACK,clear pending*/
/*66Mhz/16/(15+1) = 257.8Khz */
IICSTAT = 0x10 ; /* Enable RX/TX*/
enable_irq( IRQ_IIC ); /*enable at24c01a interrupt on ARM*/
MOD_INC_USE_COUNT;
return 0;
}
static int at24c01a_release(struct inode *inode, struct file *filp)
{
free_irq(IRQ_IIC, dev_idkp);
IICSTAT = 0; /*Disable IIC*/
MOD_DEC_USE_COUNT;
#ifdef DEBUG
printk("Successful to close AT24C01A!\n");
#endif
return 0;
}
static void at24c01a_handler(int irq, void *dev_idkp, struct pt_regs *regs)
{
#ifdef DEBUG
printk("enter at24c01a_handler()\n");
#endif
//wake_up_interruptible(&iic_queue);
ack = 1 ;
I_ISPC=BIT_IIC;
#ifdef DEBUG
printk("exit at24c01a_handler()\n\n");
#endif
}
int __init at24c01a_init(void)
{
int ret;
/*register the char device*/
if ((ret=register_chrdev(IIC_MAJOR, IIC_NAME, &at24c01a_fops))!=0)
{
printk("Failed to register "IIC_NAME "\n");
return ret;
}
#ifdef DEBUG
printk("AT24C01A driver initialized\n");
#endif
return 0;
}
void __exit at24c01a_cleanup(void)
{
//free_irq(IRQ_IIC, dev_idkp);
unregister_chrdev(IIC_MAJOR, IIC_NAME);
#ifdef DEBUG
printk("AT24C01A has been removed\n");
#endif
}
module_init(at24c01a_init);
module_exit(at24c01a_cleanup);
EXPORT_NO_SYMBOLS;
MODULE_DESCRIPTION("The driver for AT24C01A(IIC)");
MODULE_SUPPORTED_DEVICE("uClinux 2.4.x Digital Jet Printer Machine");
MODULE_AUTHOR("Zhang Dahai");
MODULE_LICENSE("GPL");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -