⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rtl8305drive.c

📁 Realteak公司8305芯片驱动demo
💻 C
字号:
/********************************************************************/
/*                 GENERAL CONSTANTS AND DEFINITIONS 	            */
/********************************************************************/

#define TRUE 	1
#define FALSE 	0
#define ON		1
#define OFF		0

/*------------------------*/
/* Fundamental Data Types */
/*------------------------*/

typedef	char		   	BYTE;
typedef unsigned char 	UBYTE;	
typedef	short		   	HWORD;	
typedef	unsigned short	UHWORD;	
typedef	long		   	WORD;	
typedef unsigned long 	UWORD;	
typedef unsigned char 	BOOL;	

typedef	volatile char		   	VBYTE;
typedef volatile unsigned char 	VUBYTE;	
typedef	volatile short		   	VHWORD;	
typedef	volatile unsigned short	VUHWORD;	
typedef	volatile long		   	VWORD;	
typedef volatile unsigned long 	VUWORD;	
typedef volatile unsigned char 	VBOOL;	

/* CPU base address defination */
#define IMMAP_BASE  0xf0000000
#define IMMAP_LENTH 0x60000


/* The major device number. We can't rely on dynamic 
 * registration any more, because ioctls need to know 
 * it. */
#define MAJOR_NUM 	100
#define	DEVICE_NAME 	"rtl8305"

/*RTL8305 relevant information */
#define MDIO_PIN_MASK 0x00000040  /* PC25 for MDIO in the 8271 of 826x */
#define MDC_PIN_MASK  0x00000200  /* PC22 for MDC in the 8271 of 826x */

#ifndef __KERNEL__
	#define __KERNEL__
#endif
#ifndef MODULE
	#define MODULE
#endif

#ifdef CONFIG_SMP
	# define __SMP__
#endif

#include <linux/kernel.h>
#include <linux/module.h> 	/*for MOD_DEC_USE_COUNT ,etc.*/#include <linux/init.h>		/* for module_init */#include <asm/errno.h>
#include <asm/immap_8260.h>
#include <linux/fs.h>		/*character device definitions*/#include <linux/wrapper.h>	/*for register_chrdev and unregister_chrdev				wrapper for compatibility with future versions*/
#include <asm/uaccess.h>  	/*for get_user and put_user*/#include <sys/mman.h>

#if CONFIG_MODVERSIONS==1
#include <linux/modversions.h>
#endif


#ifndef KERNEL_VERSION
#define KERNEL_VERSION(a,b,c)	((a)*65536+(b)*256+(c))
#endif

/***********************/
/* Global Declarations */
/***********************/
volatile immap_t *IMM  = (immap_t *)(IMMAP_BASE );  /*IMMAP_BASE; Internal Memory Map base pointer (0x30026000)*/
	
static int 	Device_Open = 0;

volatile void Z0_Send( void)  //"Z0" during reading 
{
	int j;
	//z0 =z0 
	IMM->im_ioport.iop_pdatc &= ~MDC_PIN_MASK;  /* clock fail */
	IMM->im_ioport.iop_pdirc &= ~MDIO_PIN_MASK;  /* pc25=Input low */
	for (j=0; j<10; j++)
	{
		;
	}
	
	IMM->im_ioport.iop_pdatc |= MDC_PIN_MASK;  /* clock rise */

	IMM->im_ioport.iop_pdirc |= MDIO_PIN_MASK;  /* pc25=1:output high */
	IMM->im_ioport.iop_pdatc &= ~MDC_PIN_MASK;  /* clock fail */
	IMM->im_ioport.iop_pdatc &= ~MDIO_PIN_MASK;  /* IO low */
	for (j=0; j<10; j++)
	{
		;
	}
	IMM->im_ioport.iop_pdatc |= MDC_PIN_MASK;  /* clock rise */
} /*end Z0_Send*/

volatile void Idle_Send(void)  //z* at end of frame
{
	//idle
	IMM->im_ioport.iop_pdirc |= MDIO_PIN_MASK;  /* pc25=1:output high */
	IMM->im_ioport.iop_pdatc &= ~MDIO_PIN_MASK;  /* IO low */
	IMM->im_ioport.iop_pdatc |= MDC_PIN_MASK;  /* clock rise */
	IMM->im_ioport.iop_pdatc &= ~MDC_PIN_MASK;  /* clock fail */
} /*end Idle_Send*/

volatile void MdioSend( UWORD txF, int size) 
{
  UWORD dmask;
  int i,j;    /* index */

  dmask = 1 << (size-1);  /* msbit out first */

  for ( i = 0; i < size; i++ ) 
  {  /* for "size" bits */
    IMM->im_ioport.iop_pdatc &= ~MDC_PIN_MASK;  /* clock fall */
    if ( txF & dmask ) 
    {  /* output data bit high */
      IMM->im_ioport.iop_pdatc |=  MDIO_PIN_MASK;
    }
    else 
    {  /* output data bit low, >400ns */
      IMM->im_ioport.iop_pdatc &= ~MDIO_PIN_MASK;
    }
    for (j=0; j<10; j++);
    IMM->im_ioport.iop_pdatc |= MDC_PIN_MASK;  /* clock rise */    
    for (j=0; j<10; j++);

    txF = (UWORD)(txF << 1);  /* >160ns */
  } 

} /* end MdioSend */
volatile UWORD MdioReceive(int size) 
{
  int i,j;
  UWORD rxF=0x0000;  /* index */

  IMM->im_ioport.iop_pdirc &= ~MDIO_PIN_MASK;  /* pc25=0:input */

  for ( i = 0; i < size; i++ ) 
  {  /* 16 bits */
    IMM->im_ioport.iop_pdatc |= MDC_PIN_MASK;  /* clock rise */
     if ( IMM->im_ioport.iop_pdatc & MDIO_PIN_MASK ) 
     {  /* if read in a high bit */
        rxF = ( (UHWORD)(rxF << 1) | 1 );	 /* shift in a one */
     }
     else 
     {  /* if read in a low bit */
        rxF = ( (UHWORD)(rxF << 1) & ~(UHWORD)1 );  /* shift in a zero */
     }
    for (j=0; j<10; j++);
    IMM->im_ioport.iop_pdatc &= ~MDC_PIN_MASK;  /* clock fall */    	
    for (j=0; j<10; j++);
     
  }  /* end of for loop	*/
  
  return (rxF);
} /* end MdioReceive */    

/*Prototypes*/static int rtl8305_open(struct inode *inode, struct file *file);static int rtl8305_release(struct inode *inode, struct file *file);static int rtl8305_read(struct file *file,char * buffer, size_t length, loff_t * offset);static int rtl8305_write(struct file *file,const char * buffer, size_t length, loff_t * offset);

struct file_operations rtl8305_ops = {
	.read=rtl8305_read,
	.write=rtl8305_write,
	.open=rtl8305_open,
	.release=rtl8305_release
 };

static int rtl8305_open(struct inode *inode, struct file *file)
{
	UWORD rxF;
	//int fd;
	if (Device_Open)
	{
		return -1;
	}
	
	/*To initialize the PortC registers*/
	IMM->im_ioport.iop_podrc &= ~MDIO_PIN_MASK;  //0:normal
	IMM->im_ioport.iop_podrc &= ~MDC_PIN_MASK;
	IMM->im_ioport.iop_pdirc |= MDC_PIN_MASK;       //  1:PC22 for output
	IMM->im_ioport.iop_pdirc |= MDIO_PIN_MASK;     //1:PC25 for output
	IMM->im_ioport.iop_pparc &= ~(0x00000240);   //0:PC22,PC25 as a general purpose IO
	
	/*read a Rtl8305 register for test*/
	MdioSend (0xffffffff,32);  //preamble
	MdioSend (0x01,2); //start
	MdioSend (0x02,2); //read
	MdioSend (0x00,5); //PHY0
	MdioSend (0x01,5); //PHY0-Reg1
	
	Z0_Send(); //z0 =z0 
	
	//read from rtl8305
	rxF=MdioReceive(16); //PHY0-1=0x7849
	Idle_Send();  	//idle
	
	printk(KERN_ALERT"\nIn open():PHY0-1(0x7849) =ox%lx\n",rxF);
	
	Device_Open++;
	MOD_INC_USE_COUNT;   
	
	printk(KERN_ALERT"Device Open(%p,%p)\n",inode,file);
	return 0 ;
} /*end rtl8305_open*/


static int rtl8305_read(struct file *file,char * buffer, size_t length, loff_t * offset)
{
	char rxBuf[2];	
	rxBuf[0]=* (buffer++);	rxBuf[1]=* buffer;
	
	MdioSend (0x01,2); //start	MdioSend (0x02,2); //read
	MdioSend (rxBuf[0],5); //PHY0
	MdioSend (rxBuf[1],5); //PHY0-Reg1
	Z0_Send();	//z0 =z0 	//read from rtl8305	rxBuf[0]=MdioReceive(8); //PHYx-x=high 8 bits	rxBuf[1]=MdioReceive(8); //PHYx-x=low 8 bits
	Idle_Send();		//idle	
	put_user(rxBuf[0], (--buffer));
	put_user(rxBuf[1], (++buffer));
	// printk(KERN_ALERT"register of RTL8305 =ox%x.%x \n",rxBuf[0],rxBuf[1]);
	
	return (2);
} /*end rtl8305_read*/

static int rtl8305_write(struct file *file,const char * buffer, size_t length, loff_t * offset)
{
	char rxBuf[4];
	
	rxBuf[0]=* (buffer++);
	rxBuf[1]=* (buffer++);
	rxBuf[3]=* (buffer++);
	rxBuf[4]=* (buffer);
	buffer--;buffer--;buffer--;
	MdioSend (0x01,2); //start
	MdioSend (0x01,2); //read
	MdioSend (rxBuf[0],5); //PHYx
	MdioSend (rxBuf[1],5); //Reg x
	MdioSend (0x02,2); //write 10 ,turn around
	//write to rtl8305
	MdioSend (rxBuf[2],8); //high 8 bits
	MdioSend (rxBuf[3],8); //low 8 bits
	Idle_Send();		//idle
	
	//	printk( KERN_ALERT"\nWriting PHY[%d]_Reg[%d]=ox%x.%x successful.\n",rxBuf[0],rxBuf[1],rxBuf[3],rxBuf[4] );
	
	return (4);
} /*end rtl8305_write*/

static int rtl8305_release(struct inode *inode, struct file *file)
{
	printk(KERN_ALERT"Rtl8305 device_release(%p,%p)\n",inode,file);
	
	/* We're now ready for our next caller */
	Device_Open --;
	MOD_DEC_USE_COUNT;
	return 0;
} /*end rtl8305_release*/
	
/* Initialize the module - Register the character device */
static int __init rtl8305_module_init( void )
{
	int ret_val;
	
	/* Register the character device (atleast try) */
	ret_val = register_chrdev(MAJOR_NUM, DEVICE_NAME, &rtl8305_ops);
	
	/* Negative values signify an error */
	if (ret_val < 0) {
	printk ("%s failed with %d\n",
	"Sorry, registering the Rtl8305 device ", ret_val);	
	return ret_val;
	}
	
	printk ("%s The major device number is %d.\n",
	"Rtl8305 registeration is a success",    MAJOR_NUM);
	printk ("mknod %s c %d 0\n", DEVICE_NAME,MAJOR_NUM);	
	return 0;
} /*end rtl8305_module_init*/

/* Cleanup - unregister the appropriate file from /proc */
static void __exit rtl8305_cleanup_module(void)
{
  int ret;
  
  /* Unregister the device */
  ret = unregister_chrdev(MAJOR_NUM, DEVICE_NAME);
 
  /* If there's an error, report it */ 
  if (ret < 0)
  {
  	printk(KERN_ALERT"Error in module_unregister_chrdev: %d\n", ret);
  }
  printk(KERN_ALERT"in module_unregister_chrdev: %d\n", ret);
} /*end rtl8305_cleanup_module*/

module_init(rtl8305_module_init);
module_exit(rtl8305_cleanup_module);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("by Orien Kan ,Chian University of Mining and Technology ,and , Taicom Co., Ltd ");
MODULE_DESCRIPTION("Rtl8305 driver");

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -