コード例 #1
0
ファイル: spi.c プロジェクト: OpenNuvoton/NUC970_NonOS_BSP
/**
  * @brief Get busy status of spi interface
  * @param[in] fd is interface number.
  * @return busy or not
  * @retval 0 not busy.
  * @retval 1 busy.
  */
uint8_t spiGetBusyStatus(int32_t fd)
{
    spi_dev *dev;

    dev = (spi_dev *)((uint32_t)&spi_device[fd]);

    if(spi_in(dev, CNTRL) & (0x1 << 17))
        return (!dev->intflag);
    else
        return (( spi_in(dev, CNTRL) & 0x1) == 0x1 ? 1:0);
}
コード例 #2
0
ファイル: user_io.c プロジェクト: UIKit0/mist-firmware
// read 32 bit ethernet status word from FPGA
uint32_t user_io_eth_get_status(void) {
  uint32_t s;

  spi_uio_cmd_cont(UIO_ETH_STATUS);
  s = spi_in();
  s = (s<<8) | spi_in();
  s = (s<<8) | spi_in();
  s = (s<<8) | spi_in();
  DisableIO();

  return s;
}
コード例 #3
0
ファイル: spi.c プロジェクト: OpenNuvoton/NUC970_NonOS_BSP
/**
  * @brief Read data form spi interface
  * @param[in] fd is interface number.
  * @param[in] buff_id is buffer number. If transfer number is 4, application needs read 4 times (buff_id is from 0 to 3) from buffer.
  * @return data
  */
uint32_t spiRead(int32_t fd, uint8_t buff_id)
{
    spi_dev *dev;

    dev = (spi_dev *)((uint32_t)&spi_device[fd]);
    return spi_in(dev, (RX0+4*buff_id));
}
コード例 #4
0
ファイル: enc28j60.c プロジェクト: Cjsnet/plipbox
static void readBuf(uint16_t len, uint8_t* data) {
    spi_enable_eth();
    spi_out(ENC28J60_READ_BUF_MEM);
    while (len--) {
        *data++ = spi_in();
    }
    spi_disable_eth();
}
コード例 #5
0
ファイル: user_io.c プロジェクト: UIKit0/mist-firmware
// read 8+32 bit sd card status word from FPGA
uint8_t user_io_sd_get_status(uint32_t *lba) {
  uint32_t s;
  uint8_t c; 

  spi_uio_cmd_cont(UIO_GET_SDSTAT);
  c = spi_in();
  s = spi_in();
  s = (s<<8) | spi_in();
  s = (s<<8) | spi_in();
  s = (s<<8) | spi_in();
  DisableIO();

  if(lba)
    *lba = s;

  return c;
}
コード例 #6
0
ファイル: user_io.c プロジェクト: UIKit0/mist-firmware
// 8 bit cores have a config string telling the firmware how
// to treat it
char *user_io_8bit_get_string(char index) {
  unsigned char i, lidx = 0, j = 0;
  static char buffer[32+1];  // max 32 bytes per config item

  // clear buffer
  buffer[0] = 0;

  spi_uio_cmd_cont(UIO_GET_STRING);
  i = spi_in();
  // the first char returned will be 0xff if the core doesn't support
  // config strings. atari 800 returns 0xa4 which is the status byte
  if((i == 0xff) || (i == 0xa4)) {
    DisableIO();
    return NULL;
  }

  //  iprintf("String: ");

  while ((i != 0) && (i!=0xff) && (j<sizeof(buffer))) {
    if(i == ';') {
      if(lidx == index) buffer[j++] = 0;
      lidx++;
    } else {
      if(lidx == index)
	buffer[j++] = i;
    }

    //    iprintf("%c", i);
    i = spi_in();
  }
    
  DisableIO();
  //  iprintf("\n");

  // if this was the last string in the config string list, then it still
  // needs to be terminated
  if(lidx == index)
    buffer[j] = 0;

  // also return NULL for empty strings
  if(!buffer[0]) 
    return NULL;

  return buffer;
}    
コード例 #7
0
ファイル: enc28j60.c プロジェクト: Cjsnet/plipbox
static uint8_t readOp (uint8_t op, uint8_t address) {
    spi_enable_eth();
    spi_out(op | (address & ADDR_MASK));
    if (address & 0x80)
        spi_out(0x00);
    uint8_t result = spi_in();
    spi_disable_eth();
    return result;
}
コード例 #8
0
ファイル: user_io.c プロジェクト: UIKit0/mist-firmware
char user_io_serial_status(serial_status_t *status_in, uint8_t status_out) {
  uint8_t i, *p = (uint8_t*)status_in;

  spi_uio_cmd_cont(UIO_SERIAL_STAT);

  // first byte returned by core must be "magic". otherwise the
  // core doesn't support this request
  if(SPI(status_out) != 0xa5) {
    DisableIO();
    return 0;
  }

  // read the whole structure
  for(i=0;i<sizeof(serial_status_t);i++)
    *p++ = spi_in();

  DisableIO();
  return 1;
}
コード例 #9
0
ファイル: sc8800.c プロジェクト: AndrewDB/rk3066-kernel
static int sc8800_tx(struct sc8800_data *sc8800)
{
	int ret = 0, len;

	char *buf = NULL;

	sc8800->write_tmo = 0;
	buf = kzalloc(WR_BUF_SIZE + BP_PACKET_SIZE, GFP_KERNEL);
	if(!buf){
		dev_err(sc8800->dev, "ERR: no memery for buf\n");
		return -ENOMEM;
	}
	while(!bp_rts(sc8800)){
		if(sc8800->write_tmo){
			sc8800_dbg(sc8800->dev, "bp_rts = 0\n");
			kfree(buf);
			return -1;
		}
		schedule();
	}
	mutex_lock(&sc8800s_lock);
	#if defined(CONFIG_ARCH_RK30)
	ap_rts(sc8800,1);
	#else
	ap_rts(sc8800,0);
	#endif
#if 1
	while(bp_rdy(sc8800)){
		if(sc8800->write_tmo){
			#if defined(CONFIG_ARCH_RK30)
			ap_rts(sc8800,0);
			#else
			ap_rts(sc8800,1);
			#endif
			sc8800_dbg(sc8800->dev, "ERR: %s write timeout ->bp not ready (bp_rdy = 1)\n", __func__);
			msleep(1);
			kfree(buf);
			mutex_unlock(&sc8800s_lock);
			return -1;
		}
		schedule();
	}
#endif
	len = sc8800_data_packet(buf, sc8800->tx_buf, sc8800->tx_len);
	spi_in(sc8800, buf, len, &ret);

	if(ret < 0)
		dev_err(sc8800->dev, "ERR: %s spi in err = %d\n", __func__, ret);
	#if defined(CONFIG_ARCH_RK30)
	ap_rts(sc8800,0);
	#else
	ap_rts(sc8800,1);
	#endif
	if(buf){
		kfree(buf);
		buf = NULL;
	}

	mutex_unlock(&sc8800s_lock);
#if 1	
	while(!bp_rdy(sc8800)){
		if(sc8800->write_tmo){
			dev_err(sc8800->dev, "ERR: %s write timeout -> bp receiving (bp_rdy = 0)\n", __func__);
			ret = -1;
		}
		schedule();
	}
#endif
	return ret;
}
コード例 #10
0
ファイル: user_io.c プロジェクト: UIKit0/mist-firmware
void user_io_poll() {

  if(user_io_dip_switch1()) {
    // check of core has changed from a good one to a not supported on
    // as this likely means that the user is reloading the core via jtag
    unsigned char ct;
    static unsigned char ct_cnt = 0;
    
    EnableIO();
    ct = SPI(0xff);
    DisableIO();
    SPI(0xff);      // needed for old minimig core
    
    if(ct == core_type) 
      ct_cnt = 0;        // same core type, everything is fine
    else {
      // core type has changed
      if(++ct_cnt == 255) {
	// wait for a new valid core id to appear
	while((ct &  0xf0) != 0xa0) {
	  EnableIO();
	  ct = SPI(0xff);
	  DisableIO();
	  SPI(0xff);      // needed for old minimig core
	}

	// reset io controller to cope with new core
	*AT91C_RSTC_RCR = 0xA5 << 24 | AT91C_RSTC_PERRST | AT91C_RSTC_PROCRST; // restart
	for(;;);
      }
    }
  }

  if((core_type != CORE_TYPE_MINIMIG) &&
     (core_type != CORE_TYPE_MINIMIG2) &&
     (core_type != CORE_TYPE_PACE) &&
     (core_type != CORE_TYPE_MIST) &&
     (core_type != CORE_TYPE_ARCHIE) &&
     (core_type != CORE_TYPE_8BIT)) {
    return;  // no user io for the installed core
  }

  if(core_type == CORE_TYPE_MIST) {
    char redirect = tos_get_cdc_control_redirect();

    ikbd_poll();

    // check for input data on usart
    USART_Poll();
      
    unsigned char c = 0;

    // check for incoming serial data. this is directly forwarded to the
    // arm rs232 and mixes with debug output. Useful for debugging only of
    // e.g. the diagnostic cartridge    
    if(!pl2303_is_blocked()) {
      spi_uio_cmd_cont(UIO_SERIAL_IN);
      while(spi_in() && !pl2303_is_blocked()) {
	c = spi_in();
	
	// if a serial/usb adapter is connected it has precesence over
	// any other sink
	if(pl2303_present()) 
	  pl2303_tx_byte(c);
	else {
	  if(c != 0xff) 
	    putchar(c);
	  
	  // forward to USB if redirection via USB/CDC enabled
	  if(redirect == CDC_REDIRECT_RS232)
	    cdc_control_tx(c);
	}
      }
      DisableIO();
    }
    
    // check for incoming parallel/midi data
    if((redirect == CDC_REDIRECT_PARALLEL) || (redirect == CDC_REDIRECT_MIDI)) {
      spi_uio_cmd_cont((redirect == CDC_REDIRECT_PARALLEL)?UIO_PARALLEL_IN:UIO_MIDI_IN);
      // character 0xff is returned if FPGA isn't configured
      c = 0;
      while(spi_in() && (c!= 0xff)) {
	c = spi_in();
	cdc_control_tx(c);
      }
      DisableIO();
      
      // always flush when doing midi to reduce latencies
      if(redirect == CDC_REDIRECT_MIDI)
	cdc_control_flush();
    }
  }

  // poll db9 joysticks
  static int joy0_state = JOY0;
  if((*AT91C_PIOA_PDSR & JOY0) != joy0_state) {
    joy0_state = *AT91C_PIOA_PDSR & JOY0;
    
    unsigned char joy_map = 0;
    if(!(joy0_state & JOY0_UP))    joy_map |= JOY_UP;
    if(!(joy0_state & JOY0_DOWN))  joy_map |= JOY_DOWN;
    if(!(joy0_state & JOY0_LEFT))  joy_map |= JOY_LEFT;
    if(!(joy0_state & JOY0_RIGHT)) joy_map |= JOY_RIGHT;
    if(!(joy0_state & JOY0_BTN1))  joy_map |= JOY_BTN1;
    if(!(joy0_state & JOY0_BTN2))  joy_map |= JOY_BTN2;

    user_io_joystick(joystick_renumber(0), joy_map);
  }
  
  static int joy1_state = JOY1;
  if((*AT91C_PIOA_PDSR & JOY1) != joy1_state) {
    joy1_state = *AT91C_PIOA_PDSR & JOY1;
    
    unsigned char joy_map = 0;
    if(!(joy1_state & JOY1_UP))    joy_map |= JOY_UP;
    if(!(joy1_state & JOY1_DOWN))  joy_map |= JOY_DOWN;
    if(!(joy1_state & JOY1_LEFT))  joy_map |= JOY_LEFT;
    if(!(joy1_state & JOY1_RIGHT)) joy_map |= JOY_RIGHT;
    if(!(joy1_state & JOY1_BTN1))  joy_map |= JOY_BTN1;
    if(!(joy1_state & JOY1_BTN2))  joy_map |= JOY_BTN2;
    
    user_io_joystick(joystick_renumber(1), joy_map);
  }

  user_io_send_buttons(0);

  // mouse movement emulation is continous 
  if(emu_mode == EMU_MOUSE) {
    if(CheckTimer(emu_timer)) {
      emu_timer = GetTimer(EMU_MOUSE_FREQ);
      
      if(emu_state & JOY_MOVE) {
	unsigned char b = 0;
	char x = 0, y = 0;
	if((emu_state & (JOY_LEFT | JOY_RIGHT)) == JOY_LEFT)  x = -1; 
	if((emu_state & (JOY_LEFT | JOY_RIGHT)) == JOY_RIGHT) x = +1; 
	if((emu_state & (JOY_UP   | JOY_DOWN))  == JOY_UP)    y = -1; 
	if((emu_state & (JOY_UP   | JOY_DOWN))  == JOY_DOWN)  y = +1; 
	
	if(emu_state & JOY_BTN1) b |= 1;
	if(emu_state & JOY_BTN2) b |= 2;
	
	user_io_mouse(b, x, y);
      }
    }
  }

  if((core_type == CORE_TYPE_MINIMIG) ||
     (core_type == CORE_TYPE_MINIMIG2)) {
    kbd_fifo_poll();

    // frequently check mouse for events
    if(CheckTimer(mouse_timer)) {
      mouse_timer = GetTimer(MOUSE_FREQ);

      // has ps2 mouse data been updated in the meantime
      if(mouse_flags & 0x80) {
	spi_uio_cmd_cont(UIO_MOUSE);

	// ----- X axis -------
	if(mouse_pos[X] < -128) {
	  spi8(-128);
	  mouse_pos[X] += 128;
	} else if(mouse_pos[X] > 127) {
	  spi8(127);
	  mouse_pos[X] -= 127;
	} else {
	  spi8(mouse_pos[X]);
	  mouse_pos[X] = 0;
	}

	// ----- Y axis -------
	if(mouse_pos[Y] < -128) {
	  spi8(-128);
	  mouse_pos[Y] += 128;
	} else if(mouse_pos[Y] > 127) {
	  spi8(127);
	  mouse_pos[Y] -= 127;
	} else {
	  spi8(mouse_pos[Y]);
	  mouse_pos[Y] = 0;
	}

	spi8(mouse_flags & 0x03);
	DisableIO();

	// reset flags
	mouse_flags = 0;
      }
    }
  }

  if(core_type == CORE_TYPE_MIST) {
    // do some tos specific monitoring here
    tos_poll();
  }

  if(core_type == CORE_TYPE_8BIT) {
    unsigned char c = 1, f, p=0;

    // check for input data on usart
    USART_Poll();
      
    // check for serial data to be sent

    // check for incoming serial data. this is directly forwarded to the
    // arm rs232 and mixes with debug output.
    spi_uio_cmd_cont(UIO_SIO_IN);
    // status byte is 1000000A with A=1 if data is available
    if((f = spi_in(0)) == 0x81) {
      iprintf("\033[1;36m");
      
      // character 0xff is returned if FPGA isn't configured
      while((f == 0x81) && (c!= 0xff) && (c != 0x00) && (p < 8)) {
	c = spi_in();
	if(c != 0xff && c != 0x00) 
	  iprintf("%c", c);

	f = spi_in();
	p++;
      }
      iprintf("\033[0m");
    }
    DisableIO();

    // sd card emulation
    {
      static char buffer[512];
      static uint32_t buffer_lba = 0xffffffff;
      uint32_t lba;
      uint8_t c = user_io_sd_get_status(&lba);

      // valid sd commands start with "5x" to avoid problems with
      // cores that don't implement this command
      if((c & 0xf0) == 0x50) {

	// debug: If the io controller reports and non-sdhc card, then
	// the core should never set the sdhc flag
	if((c & 3) && !MMC_IsSDHC() && (c & 0x04))
	  iprintf("WARNING: SDHC access to non-sdhc card\n");
 	
	// check if core requests configuration
	if(c & 0x08) {
	  iprintf("core requests SD config\n");
	  user_io_sd_set_config();
	}

	// check if system is trying to access a sdhc card from 
	// a sd/mmc setup

	// check if an SDHC card is inserted
	if(MMC_IsSDHC()) {
	  static char using_sdhc = 1;

	  // SD request and 
	  if((c & 0x03) && !(c & 0x04)) {
	    if(using_sdhc) {
	      // we have not been using sdhc so far? 
	      // -> complain!
	      ErrorMessage(" This core does not support\n"
			   " SDHC cards. Using them may\n"
			   " lead to data corruption.\n\n"
			   " Please use an SD card <2GB!", 0);
	      using_sdhc = 0;
	    }
	  } else
	    // SDHC request from core is always ok
	    using_sdhc = 1;
	}

	if((c & 0x03) == 0x02) {
	  // only write if the inserted card is not sdhc or
	  // if the core uses sdhc
	  if((!MMC_IsSDHC()) || (c & 0x04)) {  
	    uint8_t wr_buf[512];

	    if(user_io_dip_switch1())
	      iprintf("SD WR %d\n", lba);

	    // if we write the sector stored in the read buffer, then
	    // update the read buffer with the new contents
	    if(buffer_lba == lba) 
	      memcpy(buffer, wr_buf, 512);

	      buffer_lba = 0xffffffff;

	    // Fetch sector data from FPGA ...
	    spi_uio_cmd_cont(UIO_SECTOR_WR);
	    spi_block_read(wr_buf);
	    DisableIO();

	    // ... and write it to disk
	    DISKLED_ON;

	    if(sd_image.size) {
	      FileSeek(&sd_image, lba, SEEK_SET);
	      FileWrite(&sd_image, wr_buf);
	    } else
	      MMC_Write(lba, wr_buf);

	    DISKLED_OFF;
	  }
	}

	if((c & 0x03) == 0x01) {

	  if(user_io_dip_switch1())
	    iprintf("SD RD %d\n", lba);
	  
	  // are we using a file as the sd card image?
	  // (C64 floppy does that ...)
	  if(buffer_lba != lba) {
	    DISKLED_ON;
	    if(sd_image.size) {
	      FileSeek(&sd_image, lba, SEEK_SET);
	      FileRead(&sd_image, buffer);
	    } else {
	      // sector read
	      // read sector from sd card if it is not already present in
	      // the buffer
	      MMC_Read(lba, buffer);
	    }
	    buffer_lba = lba;
	    DISKLED_OFF;
	  }

	  if(buffer_lba == lba) {
	    // data is now stored in buffer. send it to fpga
	    spi_uio_cmd_cont(UIO_SECTOR_RD);
	    spi_block_write(buffer);
	    DisableIO();

	    // the end of this transfer acknowledges the FPGA internal
	    // sd card emulation
	  }

	  // just load the next sector now, so it may be prefetched
	  // for the next request already
	  DISKLED_ON;
	  if(sd_image.size) {
	    FileSeek(&sd_image, lba+1, SEEK_SET);
	    FileRead(&sd_image, buffer);
	  } else {
	    // sector read
	    // read sector from sd card if it is not already present in
	    // the buffer
	    MMC_Read(lba+1, buffer);
	  }
	  buffer_lba = lba+1;
	  DISKLED_OFF;
	}
      }
    }

    // frequently check ps2 mouse for events
    if(CheckTimer(mouse_timer)) {
      mouse_timer = GetTimer(MOUSE_FREQ);

      // has ps2 mouse data been updated in the meantime
      if(mouse_flags & 0x08) {
	unsigned char ps2_mouse[3];

	// PS2 format: 
	// YOvfl, XOvfl, dy8, dx8, 1, mbtn, rbtn, lbtn
	// dx[7:0]
	// dy[7:0]
	ps2_mouse[0] = mouse_flags;

	// ------ X axis -----------
	// store sign bit in first byte
	ps2_mouse[0] |= (mouse_pos[X] < 0)?0x10:0x00;
	if(mouse_pos[X] < -255) {
	  // min possible value + overflow flag
	  ps2_mouse[0] |= 0x40;
	  ps2_mouse[1] = -128;
	} else if(mouse_pos[X] > 255) {
	  // max possible value + overflow flag
	  ps2_mouse[0] |= 0x40;
	  ps2_mouse[1] = 255;
	} else 
	  ps2_mouse[1] = mouse_pos[X];

	// ------ Y axis -----------
	// store sign bit in first byte
	ps2_mouse[0] |= (mouse_pos[Y] < 0)?0x20:0x00;
	if(mouse_pos[Y] < -255) {
	  // min possible value + overflow flag
	  ps2_mouse[0] |= 0x80;
	  ps2_mouse[2] = -128;
	} else if(mouse_pos[Y] > 255) {
	  // max possible value + overflow flag
	  ps2_mouse[0] |= 0x80;
	  ps2_mouse[2] = 255;
	} else 
	  ps2_mouse[2] = mouse_pos[Y];
	
	// collect movement info and send at predefined rate
	iprintf("PS2 MOUSE: %x %d %d\n", 
		ps2_mouse[0], ps2_mouse[1], ps2_mouse[2]);

	spi_uio_cmd_cont(UIO_MOUSE);
	spi8(ps2_mouse[0]);
	spi8(ps2_mouse[1]);
	spi8(ps2_mouse[2]);
	DisableIO();

	// reset counters
	mouse_flags = 0;
	mouse_pos[X] = mouse_pos[Y] = 0;
      }
    }

    // --------------- THE FOLLOWING IS DEPRECATED AND WILL BE REMOVED ------------
    // ------------------------ USE SD CARD EMULATION INSTEAD ---------------------

    // raw sector io for the atari800 core which include a full
    // file system driver usually implemented using a second cpu
    static unsigned long bit8_status = 0;
    unsigned long status;

    /* read status byte */
    EnableFpga();
    SPI(UIO_GET_STATUS);
    status = SPI(0);
    status = (status << 8) | SPI(0);
    status = (status << 8) | SPI(0);
    status = (status << 8) | SPI(0);
    DisableFpga();

    if(status != bit8_status) {
      unsigned long sector = (status>>8)&0xffffff;
      char buffer[512];

      bit8_status = status;
      
      // sector read testing 
      DISKLED_ON;

      // sector read
      if(((status & 0xff) == 0xa5) || ((status & 0x3f) == 0x29)) {

	// extended command with 26 bits (for 32GB SDHC)
	if((status & 0x3f) == 0x29) sector = (status>>6)&0x3ffffff;

	bit8_debugf("SECIO rd %ld", sector);

	if(MMC_Read(sector, buffer)) {
	  // data is now stored in buffer. send it to fpga
	  EnableFpga();
	  SPI(UIO_SECTOR_SND);     // send sector data IO->FPGA
	  spi_block_write(buffer);
	  DisableFpga();
	} else
	  bit8_debugf("rd %ld fail", sector);
      }

      // sector write
      if(((status & 0xff) == 0xa6) || ((status & 0x3f) == 0x2a)) {

	// extended command with 26 bits (for 32GB SDHC)
	if((status & 0x3f) == 0x2a) sector = (status>>6)&0x3ffffff;

	bit8_debugf("SECIO wr %ld", sector);

	// read sector from FPGA
	EnableFpga();
	SPI(UIO_SECTOR_RCV);     // receive sector data FPGA->IO
	spi_block_read(buffer);
	DisableFpga();

	if(!MMC_Write(sector, buffer)) 
	  bit8_debugf("wr %ld fail", sector);
      }

      DISKLED_OFF;
    }
コード例 #11
0
ファイル: user_io.c プロジェクト: UIKit0/mist-firmware
// read ethernet frame from FPGAs ethernet tx buffer
void user_io_eth_receive_tx_frame(uint8_t *d, uint16_t len) {
  spi_uio_cmd_cont(UIO_ETH_FRM_IN);
  while(len--) *d++=spi_in();
  DisableIO();
}
コード例 #12
0
ファイル: spi.c プロジェクト: OpenNuvoton/NUC970_NonOS_BSP
/**
  * @brief  SPI-1 Interrupt handler
  * @param None
  * @return None
  */
static void spi1ISR(void)
{
    // clear interrupt flag
    outpw(REG_SPI1_CNTRL, spi_in((spi_dev *)((uint32_t)&spi_device[1]), CNTRL) | 0x1 << 16);
    spi_device[1].intflag = 1;
}
コード例 #13
0
ファイル: spi.c プロジェクト: OpenNuvoton/NUC970_NonOS_BSP
/**
  * @brief Support some spi driver commands for application.
  * @param[in] fd is interface number.
  * @param[in] cmd is command.
  * @param[in] arg0 is the first argument of command.
  * @param[in] arg1 is the second argument of command.
  * @return command status.
  * @retval 0 Success otherwise fail. Fail value could be
  *                                    - \ref SPI_ERR_NODEV
  *                                    - \ref SPI_ERR_IO
  *                                    - \ref SPI_ERR_ARG
  */
int32_t spiIoctl(int32_t fd, uint32_t cmd, uint32_t arg0, uint32_t arg1)
{
    spi_dev *dev;

    if(fd != 0 && fd != 1)
        return(SPI_ERR_NODEV);

    dev = (spi_dev *)((uint32_t)&spi_device[fd]);
    if(dev->openflag == 0)
        return(SPI_ERR_IO);

    switch(cmd)
    {
        case SPI_IOC_TRIGGER:
            dev->intflag = 0;
            spi_out(dev, spi_in(dev, CNTRL) | 0x1 ,CNTRL);
            break;

        case SPI_IOC_SET_INTERRUPT:
            if(arg0 == SPI_ENABLE_INTERRUPT)
                spi_out(dev, spi_in(dev, CNTRL) | (0x1<<17) ,CNTRL);
            else
                spi_out(dev, spi_in(dev, CNTRL) & ~(0x1<<17) ,CNTRL);
            break;

        case SPI_IOC_SET_SPEED:
            spiSetSpeed(dev, (uint32_t)arg0);
            break;

        case SPI_IOC_SET_DUAL_QUAD_MODE:
            if(arg0 == SPI_DISABLE_DUAL_QUAD)
            {
                spi_out(dev, (spi_in(dev, CNTRL) & ~(0x3 << 21)) ,CNTRL);
                break;
            }

            if(arg0 == SPI_DUAL_MODE)
                spi_out(dev, (spi_in(dev, CNTRL) & ~(0x3 << 21)) | (0x1 << 22) ,CNTRL);
            else
                spi_out(dev, (spi_in(dev, CNTRL) & ~(0x3 << 21)) | (0x1 << 21) ,CNTRL);
            break;

        case SPI_IOC_SET_DUAL_QUAD_DIR:
            if(arg0 == SPI_DUAL_QUAD_INPUT)
                spi_out(dev, spi_in(dev, CNTRL) & ~(0x1 << 20) ,CNTRL);
            else
                spi_out(dev, spi_in(dev, CNTRL) | (0x1 << 20) ,CNTRL);
            break;

        case SPI_IOC_SET_LSB_MSB:
            if(arg0 == SPI_MSB)
                spi_out(dev, spi_in(dev, CNTRL) & ~(0x1 << 10) ,CNTRL);
            else
                spi_out(dev, spi_in(dev, CNTRL) | (0x1 << 10) ,CNTRL);
            break;

        case SPI_IOC_SET_TX_NUM:
            if(arg0 < 4)
                spi_out(dev, (spi_in(dev, CNTRL) & ~(0x3 << 8)) | (arg0 << 8) ,CNTRL);
            else
                return SPI_ERR_ARG;
            break;

        case SPI_IOC_SET_TX_BITLEN:
            if(arg0 < 32)
                spi_out(dev, (spi_in(dev, CNTRL) & ~(0x1f << 3)) | (arg0 << 3) ,CNTRL);
            else
                return SPI_ERR_ARG;
            break;

        case SPI_IOC_SET_MODE:
            if(arg0 > SPI_MODE_3)
                return SPI_ERR_ARG;

            if(arg0 == SPI_MODE_0)
                spi_out(dev, (spi_in(dev, CNTRL) & ~((0x3<<1) | (1UL<<31))) | (1<<2) ,CNTRL);
            else if(arg0 == SPI_MODE_1)
                spi_out(dev, (spi_in(dev, CNTRL) & ~((0x3<<1) | (1UL<<31))) | (1<<1) ,CNTRL);
            else if(arg0 == SPI_MODE_2)
                spi_out(dev, (spi_in(dev, CNTRL) & ~((0x3<<1) | (1UL<<31))) | ((1UL<<31) | (1<<2)) ,CNTRL);
            else
                spi_out(dev, (spi_in(dev, CNTRL) & ~((0x3<<1) | (1UL<<31))) | ((1UL<<31) | (1<<1)) ,CNTRL);
            break;

        case SPI_IOC_ENABLE_SS:
            if(arg0 == SPI_SS_SS0)
                spi_out(dev, (spi_in(dev, SSR) & ~(0x3)) | 0x1 ,SSR);
            else if(arg0 == SPI_SS_SS1)
                spi_out(dev, (spi_in(dev, SSR) & ~(0x3)) | 0x2 ,SSR);
            else if(arg0 == SPI_SS_BOTH)
                spi_out(dev, (spi_in(dev, SSR) & ~(0x3)) | 0x3 ,SSR);
            else
                return SPI_ERR_ARG;
            break;

        case SPI_IOC_DISABLE_SS:
            if(arg0 == SPI_SS_SS0)
                spi_out(dev, (spi_in(dev, SSR) & ~(0x1)) ,SSR);
            else if(arg0 == SPI_SS_SS1)
                spi_out(dev, (spi_in(dev, SSR) & ~(0x2)) ,SSR);
            else if(arg0 == SPI_SS_BOTH)
                spi_out(dev, (spi_in(dev, SSR) & ~(0x3)) ,SSR);
            else
                return SPI_ERR_ARG;
            break;

        case SPI_IOC_SET_AUTOSS:
            if(arg0 == SPI_DISABLE_AUTOSS)
                spi_out(dev, spi_in(dev, SSR) & ~(0x1 << 3) ,SSR);
            else
                spi_out(dev, spi_in(dev, SSR) | (0x1 << 3) ,SSR);
            break;

        case SPI_IOC_SET_SS_ACTIVE_LEVEL:
            if(arg0 == SPI_SS_ACTIVE_LOW)
                spi_out(dev, spi_in(dev, SSR) & ~(0x1 << 2) ,SSR);
            else
                spi_out(dev, spi_in(dev, SSR) | (0x1 << 2) ,SSR);
        default:
            break;
    }

    return 0;
}