www.pudn.com > 422.rar > aim104.c


/* aim104.c
 * Linux serial-bus device driver.
 * Written by wang song yue  email:wsy5228@sina.com
 * This software is released under the GPL-License.
 * Version 0.1  28 october 2005
 */ 

#include 
#if defined (CONFIG_MODVERSIONS) && !defined (MODVERSIONS)
#define MODVERSIONS
#endif

#if defined (MODVERSIONS)
#include 
#endif

#include 
#include 
#include 
#include 

#include "../include/main.h"
#include "../include/aim104.h"


/*
 * IO_RANGE is the io-memory range that gets reserved, please adjust according
 * your hardware. Example: #define IO_RANGE 0x100 for i82527 chips or
 * #define IO_RANGE 0x20 for 16c554 chips in basic serial mode.
 */

#define IO_RANGE 0x08

/*
static unsigned long  cana_address;                     
static unsigned long  cana_data;                        

int getpar(void)
{ 
   if (check_mem_region(0x31E00000,100))
   { printk("can :memory alrready in use\n");
      return -EBUSY;}
 if (check_mem_region(0x31E40000,100))
   { printk("can :memory alrready in use\n");
      return -EBUSY;}

 if (!(request_mem_region(0x31E00000,100,"can")))
    {  printk("request_mem_region error\n");
    return -EBUSY; }
 if (!(request_mem_region(0x31E40000,100,"can")))
    {  printk("request_mem_region error\n");
    return -EBUSY; }

     printk("request phy_mem is ok!\n");
  cana_address=(unsigned long)ioremap(0x31e00000,100);
  cana_data=(unsigned long)ioremap(0x31E40000,100);
  
  printk("get par tmp-cana_address=0x%lx,tmp1-canna_data=0x%lx\n",cana_address,cana_data);
  return 0;
}
*/
/**
 * template_request_io: - reserve io memory
 * @io_addr: The reserved memory starts at @io_addr, wich is the module 
 * parameter @io.
 *
 * The function template_request_io() is used to reserve the io-memory. If your
 * hardware uses a dedicated memory range as hardware control registers you
 * will have to add the code to reserve this memory as well. 
 * %IO_RANGE is the io-memory range that gets reserved, please adjust according
 * your hardware. Example: #define IO_RANGE 0x100 for i82527 chips or
 * #define IO_RANGE 0x20 for sja1000 chips in basic CAN mode.
 * Return Value: The function returns zero on success or %-ENODEV on failure
 * File: src/template.c
 */
int aim104_request_io(unsigned long io_addr)
{
  // getpar( );

	if (check_region(io_addr,IO_RANGE)) {
		CANMSG("Unable to open port: 0x%lx\n",io_addr);
		return -ENODEV;
	}
	else {
		request_region(io_addr,IO_RANGE,DEVICE_NAME);
	       	DEBUGMSG("Registered IO-memory: 0x%lx - 0x%lx\n", io_addr, io_addr + IO_RANGE - 1);
	}
	return 0;
}

/**
 * template_release_io - free reserved io-memory
 * @io_addr: Start of the memory range to be released.
 *
 * The function template_release_io() is used to free reserved io-memory.
 * In case you have reserved more io memory, don't forget to free it here.
 * IO_RANGE is the io-memory range that gets released, please adjust according
 * your hardware. Example: #define IO_RANGE 0x100 for i82527 chips or
 * #define IO_RANGE 0x20 for sja1000 chips in basic CAN mode.
 * Return Value: The function always returns zero
 * File: src/template.c
 */
int aim104_release_io(unsigned long io_addr)
{
    printk("aim104_release_io\n");                                            
	release_region(io_addr,IO_RANGE);
	// 	iounmap((void*)cana_address);
	// 	iounmap((void*)cana_data);
	//	release_mem_region(0x31e00000,100);
	//	release_mem_region(0x31e40000,100);

	return 0;
}

/**
 * template_reset - hardware reset routine
 * @card: Number of the hardware card.
 *
 * The function template_reset() is used to give a hardware reset. This is 
 * rather hardware specific so I haven't included example code. Don't forget to 
 * check the reset status of the chip before returning.
 * Return Value: The function returns zero on success or %-ENODEV on failure
 * File: src/template.c
 */
int aim104_reset(int card)
{
	int i=0;
        int j=card;
        j=j*8;

	DEBUGMSG("Resetting aim104 hardware ......\n");

	
       	__raw_writel(0x0000ffff,0xff08000c);          //set the cs3
      	__raw_writel(0x02f4e39e,0xff930020);


  //      __raw_writeb(0x80,0xffd00003);
    //    udelay(20000);
//for(i=0;i<16;i++){
      // __raw_writeb(j+1,0xffd0000b);
      // printk("%x Lcr===========0x%x\n",j,__raw_readb(0xffd0000b));
  //printk("01Lcr===========0x%x\n",__raw_readb(0xffd00003));

//udelay(20000);}
//        __raw_writel(0x80,0xffb00003);
//for(i=0;i<16;i++){
      //  __raw_writeb(0x00,0xffd00001);
//printk("Lsb===========0x%x\n",__raw_readb(0xffd00000));
//printk("01Msb===========0x%x\n",__raw_readb(0xffd00001));
//udelay(20000);}

//        __raw_writeb(0x03,0xffd00003);
//        __raw_writeb(0x00,0xffd00001);
//        __raw_writeb(0x03,0xffd00004);
//printk("01interrupt===========0x%x\n",__raw_readb(0xffb00001));
                                                                                                               
//printk("05===========0x%x\n",__raw_readb(0xffb00005));
//while(1){
//while((__raw_readb(0xffd00005)&0x20)==0){;}//printk("05=============0x%x\n",__raw_readb(0xffd00005));}
 //    __raw_writeb(0x55,0xffd00000);
//udelay(20000);
  
              
        	__raw_writeb(0x00,0xffd00003+j); 
        	__raw_writeb(0x00,0xffd00001+j);                   //forbidden any interrupt!!!!!!!
    


        	udelay(100);
									
	/* Check hardware reset status chip 0 */
	
	while ((__raw_readb(0xffd00001+j)&(0x00)) && (i<=15) ) {
		udelay(20000);
		i++;
	       	}
	if (i>=15) {
	      CANMSG("Reset status timeout!\n");
          	CANMSG("Please check your hardware.\n");
		return -ENODEV;
	}
	else
         	DEBUGMSG("Chip reset status ok.\n");

	return 0;
}

#define RESET_ADDR 0x0
//#define NR_82527 0
//#define NR_SJA1000 1

/**
 * template_init_hw_data - Initialze hardware cards
 * @card: Number of the hardware card.
 *
 * The function template_init_hw_data() is used to initialize the hardware
 * structure containing information about the installed CAN-board.
 * %RESET_ADDR represents the io-address of the hardware reset register.
 * %NR_82527 represents the number of intel 82527 chips on the board.
 * %NR_SJA1000 represents the number of philips sja1000 chips on the board.
 * The flags entry can currently only be %PROGRAMMABLE_IRQ to indicate that
 * the hardware uses programmable interrupts.
 * Return Value: The function always returns zero
 * File: src/template.c
 */
int aim104_init_hw_data(int card) 
{
	candevices_p[card]->res_addr=RESET_ADDR;
	candevices_p[card]->nr_16c554_chips=1;
	candevices_p[card]->flags |= ~PROGRAMMABLE_IRQ;

	return 0;
}

#define CHIP_TYPE "16c554"
/**
 * template_init_chip_data - Initialize chips
 * @card: Number of the hardware card
 * @chipnr: Number of the CAN chip on the hardware card
 *
 * The function template_init_chip_data() is used to initialize the hardware
 * structure containing information about the CAN chips.
 * %CHIP_TYPE represents the type of CAN chip. %CHIP_TYPE can be "i82527" or
 * "sja1000".
 * The @chip_base_addr entry represents the start of the 'official' memory map
 * of the installed chip. It's likely that this is the same as the @io_addr
 * argument supplied at module loading time.
 * The @clock entry holds the chip clock value in Hz.
 * The entry @sja_cdr_reg holds hardware specific options for the Clock Divider
 * register. Options defined in the %sja1000.h file:
 * %CDR_CLKOUT_MASK, %CDR_CLK_OFF, %CDR_RXINPEN, %CDR_CBP, %CDR_PELICAN
 * The entry @sja_ocr_reg holds hardware specific options for the Output Control
 * register. Options defined in the %sja1000.h file:
 * %OCR_MODE_BIPHASE, %OCR_MODE_TEST, %OCR_MODE_NORMAL, %OCR_MODE_CLOCK,
 * %OCR_TX0_LH, %OCR_TX1_ZZ.
 * The entry @int_clk_reg holds hardware specific options for the Clock Out
 * register. Options defined in the %i82527.h file:
 * %iCLK_CD0, %iCLK_CD1, %iCLK_CD2, %iCLK_CD3, %iCLK_SL0, %iCLK_SL1.
 * The entry @int_bus_reg holds hardware specific options for the Bus 
 * Configuration register. Options defined in the %i82527.h file:
 * %iBUS_DR0, %iBUS_DR1, %iBUS_DT1, %iBUS_POL, %iBUS_CBY.
 * Return Value: The function always returns zero
 * File: src/template.c
 */
int aim104_init_chip_data(int card, int chipnr)
{
	candevices_p[card]->chip[chipnr]->chip_type=CHIP_TYPE;
	candevices_p[card]->chip[chipnr]->chip_base_addr=io[card]; //  wangsy: candevices_p[card]->io_addr;
	candevices_p[card]->chip[chipnr]->clock = 1843200;
	candevices_p[card]->chip[chipnr]->flags = 0;
	candevices_p[card]->chip[chipnr]->c554_ier_reg = 0x0f;        //all intrupt on!!
	candevices_p[card]->chip[chipnr]->c554_fcr_reg = 0xc7;        //FCR   

	return 0;
}

/**
 * template_init_obj_data - Initialize message buffers
 * @chipnr: Number of the CAN chip
 * @objnr: Number of the message buffer
 *
 * The function template_init_obj_data() is used to initialize the hardware
 * structure containing information about the different message objects on the
 * CAN chip. In case of the sja1000 there's only one message object but on the
 * i82527 chip there are 15.
 * The code below is for a i82527 chip and initializes the object base addresses
 * The entry @obj_base_addr represents the first memory address of the message 
 * object. In case of the sja1000 @obj_base_addr is taken the same as the chips
 * base address.
 * Unless the hardware uses a segmented memory map, flags can be set zero.
 * Return Value: The function always returns zero
 * File: src/template.c
 */
int aim104_init_obj_data(int chipnr, int objnr)
{
	chips_p[chipnr]->msgobj[objnr]->obj_base_addr=chips_p[chipnr]->chip_base_addr;
	chips_p[chipnr]->msgobj[objnr]->flags=0;
//	printk("obj_base_addr=0x%x\n", chips_p[chipnr]->msgobj[objnr]->obj_base_addr);
	return 0;
}

/**
 * template_program_irq - program interrupts
 * @card: Number of the hardware card.
 *
 * The function template_program_irq() is used for hardware that uses 
 * programmable interrupts. If your hardware doesn't use programmable interrupts
 * you should not set the @candevices_t->flags entry to %PROGRAMMABLE_IRQ and 
 * leave this function unedited. Again this function is hardware specific so 
 * there's no example code.
 * Return value: The function returns zero on success or %-ENODEV on failure
 * File: src/template.c
 */
int aim104_program_irq(int card)
{
	return 0;
}

/**
 * template_write_register - Low level write register routine
 * @data: data to be written
 * @address: memory address to write to
 *
 * The function template_write_register() is used to write to hardware registers
 * on the CAN chip. You should only have to edit this function if your hardware
 * uses some specific write process.
 * Return Value: The function does not return a value
 * File: src/template.c
 */
void aim104_write_register(unsigned char data, unsigned long address)
{
//printk("aim104_writer_register!tts_io_address======0x%x\n",tts_io_addr);
   __raw_writeb(data,(tts_io_addr+address));

}

/**
 * template_read_register - Low level read register routine
 * @address: memory address to read from
 *
 * The function template_read_register() is used to read from hardware registers
 * on the CAN chip. You should only have to edit this function if your hardware
 * uses some specific read process.
 * Return Value: The function returns the value stored in @address
 * File: src/template.c
 */
unsigned aim104_read_register(unsigned long address)
{
         
     return  __raw_readb(tts_io_addr+address);
    
}

/* !!! Don't change this function !!! */
int aim104_register(struct hwspecops_t *hwspecops)
{
	hwspecops->request_io = aim104_request_io;
	hwspecops->release_io = aim104_release_io;
	hwspecops->reset = aim104_reset;
	hwspecops->init_hw_data = aim104_init_hw_data;
	hwspecops->init_chip_data = aim104_init_chip_data;
	hwspecops->init_obj_data = aim104_init_obj_data;
	hwspecops->write_register = aim104_write_register;
	hwspecops->read_register = aim104_read_register;
	hwspecops->program_irq = aim104_program_irq;
	return 0;
}