?? 1wire.c
字號:
/*! \brief file header
* the source file for 1wire driver
*
* File Name: onewire.c
*
* Programers:
*
* Date of Creations: 20 Oct,2003
*
* Synopsis:
*
* Descirption:
* Driver for the DB-MX21 OneWire
*
* Modification History:
*
*
*/
#include <linux/module.h>
#include <linux/version.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/delay.h>
#include <linux/poll.h>
#include <asm/uaccess.h>
#include <linux/string.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/types.h>
#include <linux/fcntl.h>
#include <linux/interrupt.h>
#include <linux/ptrace.h>
#include <linux/ioport.h>
#include <linux/in.h>
#include <linux/miscdevice.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <linux/string.h>
#include <linux/init.h>
#include <asm/bitops.h>
#include <asm/io.h>
#include <linux/errno.h>
#include <linux/tqueue.h>
#include <linux/wait.h>
#include <asm/irq.h>
#include <asm/arch/hardware.h>
#include <asm/arch/irqs.h>
#include <asm/arch/mx2.h>
#include <linux/pm.h>
///register definition
#define _reg_OWIRE_CTRL0 (*((volatile u16*)(MX2_IO_ADDRESS(0x10009000)))) /// 16bit owire control reg
#define _reg_OWIRE_TIME_DIV0 (*((volatile u16*)(MX2_IO_ADDRESS(0x10009002)))) /// 16bit owire time divider reg
#define _reg_OWIRE_RESET0 (*((volatile u16*)(MX2_IO_ADDRESS(0x10009004)))) /// 16bit owire reset reg
#define MODULE_NAME "Owire"
//#define DBMX_DEBUG 1
#ifdef DBMX_DEBUG
#define TRACE(fmt, args...) \
{ \
printk("\n %s:%d:%s:",__FILE__, __LINE__,__FUNCTION__); \
printk(fmt, ## args);\
}
#else
#define TRACE(fmt, args...)
#endif
#define FAILED(fmt, args...) \
{ \
printk("\n %s:%d:%s:",__FILE__, __LINE__,__FUNCTION__); \
printk(fmt, ## args);\
}
#define INFO(fmt, args...) \
{ \
printk("\n"); \
printk(fmt, ## args);\
}
///Private Function Declearation
static int Owire_open(struct inode * inode,
struct file * filp);
static int Owire_release(struct inode * inode,
struct file * filp);
static int Owire_fasync(int fd,
struct file *filp,
int mode);
ssize_t Owire_read(struct file * filp,
char * buf,
size_t count,
loff_t * l);
static ssize_t Owire_write(struct file *file,
const char *buffer,
size_t count,
loff_t *ppos);
static int Owire_ioctl(struct inode * inode,
struct file *filp,
unsigned int cmd ,
unsigned long arg);
static unsigned int Owire_poll(struct file * filp,
struct poll_table_struct * wait);
/// globale variables
struct file_operations g_Owire_fops = {
open: Owire_open,
release: Owire_release,
write: Owire_write,
read: Owire_read,
poll: Owire_poll,
ioctl: Owire_ioctl,
fasync: Owire_fasync,
};
static devfs_handle_t g_devfs_handle;
int g_Owire_major = 0;
struct pm_dev *g_Owire_pm;
static int g_Owire_status;
#define OWIRE_OPEN_STATUS 0x0001
#define OWIRE_SUSPEND_STATUS 0x0002
/**
* Function Name: Owire_open
*
* Input: inode :
* filp :
* Value Returned: int : Return status.If no error, return 0.
*
* Description: allocate resource when open the inode
*
*/
int Owire_open(struct inode * inode, struct file * filp)
{
///set AIPI1_PSR0 bit[9] and clear AIPI1_PSR1bit[9] to match 1-wire bus width 16bits
_reg_AIPI1_PSR0 |= 0x00200;
_reg_AIPI1_PSR1 &= ~0x00200;
TRACE("_reg_AIPI1_PSR0=%x, _reg_AIPI1_PSR1=%x \n",_reg_AIPI1_PSR0,_reg_AIPI1_PSR1);
///enable clk
_reg_CRM_PCCR1 |= 0x80000000;
///GPIO config
_reg_GPIO_GIUS(GPIOE) &= ~0x00010000;
_reg_GPIO_GPR(GPIOE) |= 0x00010000;
///reset the 1-wire module
_reg_OWIRE_RESET0 |= 1;
_reg_OWIRE_RESET0 = 0;
///set the time devider to get the 1M clk from the main clock
_reg_OWIRE_TIME_DIV0 = 0x2B;
_reg_OWIRE_CTRL0 |= 0x80;//control register bit 7 = 1;
///check if PST is set
udelay(610);
TRACE("_reg_OWIRE_CTRL0 = %x \n",_reg_OWIRE_CTRL0);
///check if RPP self cleared
udelay(400);
TRACE("_reg_OWIRE_CTRL0 = %x \n",_reg_OWIRE_CTRL0);
g_Owire_status = OWIRE_OPEN_STATUS;
MOD_INC_USE_COUNT;
return 0;
}
/*!
* Function Name: Owire_release
*
* Input: inode :
* filp :
* Value Returned: int : Return status.If no error, return 0.
*
* Description: release resource when close the inode
*
*/
int Owire_release(struct inode * inode, struct file * filp)
{
g_Owire_status &= ~OWIRE_OPEN_STATUS;
//disable clk
_reg_CRM_PCCR1 &= ~0x80000000;
MOD_DEC_USE_COUNT;
return 0;
}
/**
* Function Name: Owire_read
*
* Input: filp : the file
* buf : data buffer
* count : number of chars to be readed
* l : offset of file
* Value Returned: int : Return status.If no error, return 0.
*
* Description: read device driver
*
*/
ssize_t Owire_read(struct file * filp, char * buf, size_t count, loff_t * l)
{
int i,j;
char tmp,value;
char *pBuf;
pBuf = buf;
TRACE("count = %d \n",count);
for(i=0;i<count;i++)
{
value = 0;
for(j=0;j<8;j++)
{
///control register bit 4 = 1
//_reg_OWIRE_CTRL0 &= 0xEF;
_reg_OWIRE_CTRL0 |= 0x10;
udelay(117);
tmp = (_reg_OWIRE_CTRL0 & 0x08)? 1:0;
value |= tmp<<j;
}
TRACE("value %d = %x \n",i,value);
__copy_to_user(pBuf,&value,1);
pBuf++;
}
TRACE("read finished \n");
return count;
}
/**
* Function Name: Owire_write
*
* Input: filp : the file
* buf : data buffer
* count : number of chars to be read
* l : offset of file
* Value Returned: int : Return status.If no error, return 0.
*
* Description: write device driver
*
*/
ssize_t Owire_write(struct file *file, const char *buffer, size_t count, loff_t *ppos)
{
int i,j;
char value,tmp;
for(i=0;i<count;i++)
{
__copy_from_user(&value,buffer,1);
TRACE("value = %x \n",value);
for(j=0; j<8; j++)
{
tmp = value & 0x01;
if(tmp == 0)
{///control register bit 5 = 1
_reg_OWIRE_CTRL0 |= 0x20;
udelay(117);
}
else if(tmp == 1)
{///control register bit 4 = 1
_reg_OWIRE_CTRL0 |= 0x10;
udelay(117);
}
value>>=1;
}
buffer++;
}
TRACE("write finished \n");
return count;
}
/**
* Function Name: Owire_fasync
*
* Input: fd :
* filp :
* mode :
* Value Returned: int : Return status.If no error, return 0.
*
* Description: provide fasync functionality for select system call
*
*/
static int Owire_fasync(int fd, struct file *filp, int mode)
{
return 0;
}
/**
* Function Name: check_device
*
* Input: inode :
* Value Returned: int : Return status.If no error, return 0.
*
* Description: verify if the inode is a correct inode
*
*/
static int check_device(struct inode *pInode)
{
int minor;
kdev_t dev = pInode->i_rdev;
if( MAJOR(dev) != g_Owire_major)
{
printk("Owire: check_device bad major = %d\n",MAJOR(dev) );
return -1;
}
minor = MINOR(dev);
if ( minor < 1 )
return minor;
else
{
printk("Owire: check_device bad minor = %d\n",minor );
return -1;
}
}
/**
* Function Name: Owire_ioctl
*
* Input: inode :
* filp :
* cmd : command for ioctl
* arg : parameter for command
* Value Returned: int : Return status.If no error, return 0.
*
* Description: ioctl for this device driver
*
*
*/
int Owire_ioctl(struct inode * inode,
struct file *filp,
unsigned int cmd ,
unsigned long arg)
{
int ret = -EIO;
int minor;
minor = check_device( inode );
if ( minor == - 1)
{
printk("OneWire_ioctl:bad minor\n");
return -ENODEV;
}
printk("OneWire_ioctl:minor=%08x cmd=%d\n",minor,cmd);
return ret;
}
/**
* Function Name: Owire_poll
*
* Input: filp :
* wait :
* Value Returned: int : Return status.If no error, return 0.
*
* Description: support poll and select
*
*/
unsigned int Owire_poll(struct file * filp, struct poll_table_struct * wait)
{
return 0;
}
int Owire_pm_handler(struct pm_dev *dev, pm_request_t rqst, void *data)
{
switch(rqst){
case PM_RESUME:
if((g_Owire_status & OWIRE_SUSPEND_STATUS)!=0)
{
//enable clk
_reg_CRM_PCCR1 |= 0x80000000;
g_Owire_status &= ~OWIRE_SUSPEND_STATUS;
}
break;
case PM_SUSPEND:
if((g_Owire_status & OWIRE_OPEN_STATUS)!=0)
{
//disable clk
_reg_CRM_PCCR1 &= ~0x80000000;
g_Owire_status |= OWIRE_SUSPEND_STATUS;
}
break;
default:
break;
}
return 0;
}
/**
* Function Name: init_module
*
* Input: void :
* Value Returned: int : Return status.If no error, return 0.
*
* Description: device driver initialization
*
*/
#ifdef MODULE
int init_module(void)
#else
int __init Owire_init(void)
#endif
{
/* register our character device */
g_Owire_major = devfs_register_chrdev(0, MODULE_NAME, &g_Owire_fops);
if ( g_Owire_major < 0 )
{
TRACE("%s driver: Unable to register driver\n",MODULE_NAME);
return -ENODEV;
}
g_devfs_handle = devfs_register(NULL, MODULE_NAME, DEVFS_FL_DEFAULT,
g_Owire_major, 0,
S_IFCHR | S_IRUSR | S_IWUSR,
&g_Owire_fops, NULL);
g_Owire_pm = pm_register(PM_SYS_DEV,PM_SYS_VGA,Owire_pm_handler);
g_Owire_status = 0;
INFO("Owire Driver 0.1.0\n");
INFO("Motorols SPS-Suzhou\n");
return 0;
}
/******************************************************************************
* Function Name: Owire_cleanup
*
* Input: void :
* Value Returned: void :
*
* Description: clean up and free all of resource for this MODULE
*
* Modification History:
*
*****************************************************************************/
#ifdef MODULE
void cleanup_module(void)
#else
void __exit Owire_cleanup(void)
#endif
{
devfs_unregister_chrdev(g_Owire_major, MODULE_NAME);
devfs_unregister(g_devfs_handle);
pm_unregister(g_Owire_pm);
}
#ifndef MODULE
module_init(Owire_init);
module_exit(Owire_cleanup);
#endif
/* end of file */
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -